@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.
- package/README.md +6 -4
- package/VERSION +2 -2
- package/dist/commands/auth/generate.js +184 -46
- package/dist/commands/auth/generate.js.map +1 -1
- package/dist/commands/auth/login.js +234 -93
- package/dist/commands/auth/login.js.map +1 -1
- package/dist/commands/auth/logout.js +170 -30
- package/dist/commands/auth/logout.js.map +1 -1
- package/dist/commands/auth/migrate.js +216 -76
- package/dist/commands/auth/migrate.js.map +1 -1
- package/dist/commands/auth/whoami.js +145 -17
- package/dist/commands/auth/whoami.js.map +1 -1
- package/dist/commands/billing/cancel.js +164 -30
- package/dist/commands/billing/cancel.js.map +1 -1
- package/dist/commands/billing/status.js +213 -80
- package/dist/commands/billing/status.js.map +1 -1
- package/dist/commands/billing/subscribe.js +179 -45
- package/dist/commands/billing/subscribe.js.map +1 -1
- package/dist/commands/compute/app/create.js +148 -20
- package/dist/commands/compute/app/create.js.map +1 -1
- package/dist/commands/compute/app/deploy.js +244 -146
- package/dist/commands/compute/app/deploy.js.map +1 -1
- package/dist/commands/compute/app/info.js +2 -1
- package/dist/commands/compute/app/info.js.map +1 -1
- package/dist/commands/compute/app/list.js +194 -111
- package/dist/commands/compute/app/list.js.map +1 -1
- package/dist/commands/compute/app/logs.js +105 -20
- package/dist/commands/compute/app/logs.js.map +1 -1
- package/dist/commands/compute/app/profile/set.js +153 -64
- package/dist/commands/compute/app/profile/set.js.map +1 -1
- package/dist/commands/compute/app/start.js +132 -43
- package/dist/commands/compute/app/start.js.map +1 -1
- package/dist/commands/compute/app/stop.js +132 -43
- package/dist/commands/compute/app/stop.js.map +1 -1
- package/dist/commands/compute/app/terminate.js +131 -44
- package/dist/commands/compute/app/terminate.js.map +1 -1
- package/dist/commands/compute/app/upgrade.js +210 -109
- package/dist/commands/compute/app/upgrade.js.map +1 -1
- package/dist/commands/compute/environment/list.js +104 -12
- package/dist/commands/compute/environment/list.js.map +1 -1
- package/dist/commands/compute/environment/set.js +103 -18
- package/dist/commands/compute/environment/set.js.map +1 -1
- package/dist/commands/compute/environment/show.js +122 -30
- package/dist/commands/compute/environment/show.js.map +1 -1
- package/dist/commands/compute/undelegate.js +113 -13
- package/dist/commands/compute/undelegate.js.map +1 -1
- package/dist/commands/telemetry.js +213 -0
- package/dist/commands/telemetry.js.map +1 -0
- package/dist/commands/upgrade.js +159 -19
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/commands/version.js +163 -23
- package/dist/commands/version.js.map +1 -1
- package/package.json +2 -2
|
@@ -50,6 +50,7 @@ import * as path from "path";
|
|
|
50
50
|
import * as os from "os";
|
|
51
51
|
import { load as loadYaml, dump as dumpYaml } from "js-yaml";
|
|
52
52
|
import { getBuildType } from "@layr-labs/ecloud-sdk";
|
|
53
|
+
import * as crypto from "crypto";
|
|
53
54
|
var GLOBAL_CONFIG_FILE = "config.yaml";
|
|
54
55
|
var PROFILE_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
55
56
|
function getGlobalConfigDir() {
|
|
@@ -85,10 +86,39 @@ function loadGlobalConfig() {
|
|
|
85
86
|
};
|
|
86
87
|
}
|
|
87
88
|
}
|
|
89
|
+
function saveGlobalConfig(config) {
|
|
90
|
+
const configPath = getGlobalConfigPath();
|
|
91
|
+
const configDir = path.dirname(configPath);
|
|
92
|
+
fs.mkdirSync(configDir, { recursive: true, mode: 493 });
|
|
93
|
+
const content = dumpYaml(config, { lineWidth: -1 });
|
|
94
|
+
fs.writeFileSync(configPath, content, { mode: 420 });
|
|
95
|
+
}
|
|
88
96
|
function getDefaultEnvironment() {
|
|
89
97
|
const config = loadGlobalConfig();
|
|
90
98
|
return config.default_environment;
|
|
91
99
|
}
|
|
100
|
+
function getGlobalTelemetryPreference() {
|
|
101
|
+
const config = loadGlobalConfig();
|
|
102
|
+
return config.telemetry_enabled;
|
|
103
|
+
}
|
|
104
|
+
function getOrCreateUserUUID() {
|
|
105
|
+
const config = loadGlobalConfig();
|
|
106
|
+
if (config.user_uuid) {
|
|
107
|
+
return config.user_uuid;
|
|
108
|
+
}
|
|
109
|
+
const uuid = generateUUID();
|
|
110
|
+
config.user_uuid = uuid;
|
|
111
|
+
config.first_run = false;
|
|
112
|
+
saveGlobalConfig(config);
|
|
113
|
+
return uuid;
|
|
114
|
+
}
|
|
115
|
+
function generateUUID() {
|
|
116
|
+
const bytes = crypto.randomBytes(16);
|
|
117
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
118
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
119
|
+
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0"));
|
|
120
|
+
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("");
|
|
121
|
+
}
|
|
92
122
|
|
|
93
123
|
// src/utils/appNames.ts
|
|
94
124
|
import * as fs2 from "fs";
|
|
@@ -134,14 +164,6 @@ function getAppName(environment, appID) {
|
|
|
134
164
|
return "";
|
|
135
165
|
}
|
|
136
166
|
|
|
137
|
-
// src/utils/version.ts
|
|
138
|
-
function getCliVersion() {
|
|
139
|
-
return true ? "0.1.0-rc.1" : "0.0.0";
|
|
140
|
-
}
|
|
141
|
-
function getClientId() {
|
|
142
|
-
return `ecloud-cli/v${getCliVersion()}`;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
167
|
// src/utils/appResolver.ts
|
|
146
168
|
var CHUNK_SIZE = 10;
|
|
147
169
|
async function getAppInfosChunked(userApiClient, appIds, addressCount) {
|
|
@@ -441,6 +463,66 @@ function printAppDisplay(display, log, indent = " ", options = {}) {
|
|
|
441
463
|
|
|
442
464
|
// src/commands/compute/app/list.ts
|
|
443
465
|
import chalk2 from "chalk";
|
|
466
|
+
|
|
467
|
+
// src/telemetry.ts
|
|
468
|
+
import {
|
|
469
|
+
createTelemetryClient,
|
|
470
|
+
createAppEnvironment,
|
|
471
|
+
createMetricsContext,
|
|
472
|
+
addMetric,
|
|
473
|
+
addMetricWithDimensions,
|
|
474
|
+
emitMetrics,
|
|
475
|
+
getBuildType as getBuildType2
|
|
476
|
+
} from "@layr-labs/ecloud-sdk";
|
|
477
|
+
function createCLITelemetryClient() {
|
|
478
|
+
const userUUID = getOrCreateUserUUID();
|
|
479
|
+
const environment = createAppEnvironment(userUUID);
|
|
480
|
+
const telemetryEnabled = getGlobalTelemetryPreference();
|
|
481
|
+
return createTelemetryClient(environment, "ecloud-cli", {
|
|
482
|
+
telemetryEnabled: telemetryEnabled === true
|
|
483
|
+
// Only enabled if explicitly set to true
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
async function withTelemetry(command, action) {
|
|
487
|
+
const client = createCLITelemetryClient();
|
|
488
|
+
const metrics = createMetricsContext();
|
|
489
|
+
metrics.properties["source"] = "ecloud-cli";
|
|
490
|
+
metrics.properties["command"] = command.id || command.constructor.name;
|
|
491
|
+
const environment = getDefaultEnvironment() || "sepolia";
|
|
492
|
+
metrics.properties["environment"] = environment;
|
|
493
|
+
const buildType = getBuildType2() || "prod";
|
|
494
|
+
metrics.properties["build_type"] = buildType;
|
|
495
|
+
const cliVersion = command.config.version;
|
|
496
|
+
if (cliVersion) {
|
|
497
|
+
metrics.properties["cli_version"] = cliVersion;
|
|
498
|
+
}
|
|
499
|
+
addMetric(metrics, "Count", 1);
|
|
500
|
+
let actionError;
|
|
501
|
+
let result;
|
|
502
|
+
try {
|
|
503
|
+
result = await action();
|
|
504
|
+
return result;
|
|
505
|
+
} catch (err) {
|
|
506
|
+
actionError = err instanceof Error ? err : new Error(String(err));
|
|
507
|
+
throw err;
|
|
508
|
+
} finally {
|
|
509
|
+
const resultValue = actionError ? "Failure" : "Success";
|
|
510
|
+
const dimensions = {};
|
|
511
|
+
if (actionError) {
|
|
512
|
+
dimensions["error"] = actionError.message;
|
|
513
|
+
}
|
|
514
|
+
addMetricWithDimensions(metrics, resultValue, 1, dimensions);
|
|
515
|
+
const duration = Date.now() - metrics.startTime.getTime();
|
|
516
|
+
addMetric(metrics, "DurationMilliseconds", duration);
|
|
517
|
+
try {
|
|
518
|
+
await emitMetrics(client, metrics);
|
|
519
|
+
await client.close();
|
|
520
|
+
} catch {
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// src/commands/compute/app/list.ts
|
|
444
526
|
var AppList = class _AppList extends Command {
|
|
445
527
|
static description = "List all deployed apps";
|
|
446
528
|
static flags = {
|
|
@@ -456,120 +538,121 @@ var AppList = class _AppList extends Command {
|
|
|
456
538
|
})
|
|
457
539
|
};
|
|
458
540
|
async run() {
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
const result = await getAllAppsByDeveloper3(rpcUrl, environmentConfig, developerAddr);
|
|
471
|
-
if (result.apps.length === 0) {
|
|
472
|
-
this.log(`
|
|
473
|
-
No apps found for developer ${developerAddr}`);
|
|
474
|
-
return;
|
|
475
|
-
}
|
|
476
|
-
const filteredApps = [];
|
|
477
|
-
const filteredConfigs = [];
|
|
478
|
-
for (let i = 0; i < result.apps.length; i++) {
|
|
479
|
-
const config = result.appConfigs[i];
|
|
480
|
-
if (!flags.all && config.status === ContractAppStatusTerminated) {
|
|
481
|
-
continue;
|
|
541
|
+
return withTelemetry(this, async () => {
|
|
542
|
+
const { flags } = await this.parse(_AppList);
|
|
543
|
+
const validatedFlags = await validateCommonFlags(flags);
|
|
544
|
+
const environment = validatedFlags.environment || "sepolia";
|
|
545
|
+
const environmentConfig = getEnvironmentConfig2(environment);
|
|
546
|
+
const rpcUrl = validatedFlags["rpc-url"] || environmentConfig.defaultRPCURL;
|
|
547
|
+
const privateKey = validatedFlags["private-key"];
|
|
548
|
+
const account = privateKeyToAccount3(privateKey);
|
|
549
|
+
const developerAddr = account.address;
|
|
550
|
+
if (flags.verbose) {
|
|
551
|
+
this.log(`Fetching apps for developer: ${developerAddr}`);
|
|
482
552
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
}
|
|
486
|
-
if (filteredApps.length === 0) {
|
|
487
|
-
if (flags.all) {
|
|
553
|
+
const result = await getAllAppsByDeveloper3(rpcUrl, environmentConfig, developerAddr);
|
|
554
|
+
if (result.apps.length === 0) {
|
|
488
555
|
this.log(`
|
|
489
556
|
No apps found for developer ${developerAddr}`);
|
|
490
|
-
|
|
491
|
-
this.log(
|
|
492
|
-
`
|
|
493
|
-
No active apps found for developer ${developerAddr} (use --all to show terminated apps)`
|
|
494
|
-
);
|
|
557
|
+
return;
|
|
495
558
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
559
|
+
const filteredApps = [];
|
|
560
|
+
const filteredConfigs = [];
|
|
561
|
+
for (let i = 0; i < result.apps.length; i++) {
|
|
562
|
+
const config = result.appConfigs[i];
|
|
563
|
+
if (!flags.all && config.status === ContractAppStatusTerminated) {
|
|
564
|
+
continue;
|
|
565
|
+
}
|
|
566
|
+
filteredApps.push(result.apps[i]);
|
|
567
|
+
filteredConfigs.push(config);
|
|
568
|
+
}
|
|
569
|
+
if (filteredApps.length === 0) {
|
|
570
|
+
if (flags.all) {
|
|
571
|
+
this.log(`
|
|
572
|
+
No apps found for developer ${developerAddr}`);
|
|
573
|
+
} else {
|
|
574
|
+
this.log(
|
|
575
|
+
`
|
|
576
|
+
No active apps found for developer ${developerAddr} (use --all to show terminated apps)`
|
|
577
|
+
);
|
|
504
578
|
}
|
|
505
|
-
return
|
|
506
|
-
}
|
|
507
|
-
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
const userApiClient = new UserApiClient3(environmentConfig, privateKey, rpcUrl);
|
|
582
|
+
const [appInfos, releaseBlockNumbers] = await Promise.all([
|
|
583
|
+
getAppInfosChunked(userApiClient, filteredApps, 1).catch((err) => {
|
|
584
|
+
if (flags.verbose) {
|
|
585
|
+
this.warn(`Could not fetch app info from UserAPI: ${err}`);
|
|
586
|
+
}
|
|
587
|
+
return [];
|
|
588
|
+
}),
|
|
589
|
+
getAppLatestReleaseBlockNumbers(rpcUrl, environmentConfig, filteredApps).catch((err) => {
|
|
590
|
+
if (flags.verbose) {
|
|
591
|
+
this.warn(`Could not fetch release block numbers: ${err}`);
|
|
592
|
+
}
|
|
593
|
+
return /* @__PURE__ */ new Map();
|
|
594
|
+
})
|
|
595
|
+
]);
|
|
596
|
+
const blockNumbers = Array.from(releaseBlockNumbers.values()).filter((n) => n > 0);
|
|
597
|
+
const blockTimestamps = blockNumbers.length > 0 ? await getBlockTimestamps(rpcUrl, environmentConfig, blockNumbers).catch((err) => {
|
|
508
598
|
if (flags.verbose) {
|
|
509
|
-
this.warn(`Could not fetch
|
|
599
|
+
this.warn(`Could not fetch block timestamps: ${err}`);
|
|
510
600
|
}
|
|
511
601
|
return /* @__PURE__ */ new Map();
|
|
512
|
-
})
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
(
|
|
527
|
-
);
|
|
528
|
-
const profileName = apiInfo?.profile?.name;
|
|
529
|
-
const localName = getAppName(environment, appAddr);
|
|
530
|
-
const appName = profileName || localName;
|
|
531
|
-
const status = apiInfo?.status || getContractStatusString(config.status);
|
|
532
|
-
const releaseBlockNumber = releaseBlockNumbers.get(appAddr);
|
|
533
|
-
const releaseTimestamp = releaseBlockNumber ? blockTimestamps.get(releaseBlockNumber) : void 0;
|
|
534
|
-
appItems.push({ appAddr, apiInfo, appName, status, releaseTimestamp });
|
|
535
|
-
}
|
|
536
|
-
appItems.sort((a, b) => {
|
|
537
|
-
const aPriority = getStatusSortPriority(a.status);
|
|
538
|
-
const bPriority = getStatusSortPriority(b.status);
|
|
539
|
-
if (aPriority !== bPriority) {
|
|
540
|
-
return aPriority - bPriority;
|
|
541
|
-
}
|
|
542
|
-
const aTime = a.releaseTimestamp || 0;
|
|
543
|
-
const bTime = b.releaseTimestamp || 0;
|
|
544
|
-
return bTime - aTime;
|
|
545
|
-
});
|
|
546
|
-
console.log();
|
|
547
|
-
this.log(chalk2.bold(`Apps for ${developerAddr} (${environment}):`));
|
|
548
|
-
console.log();
|
|
549
|
-
for (let i = 0; i < appItems.length; i++) {
|
|
550
|
-
const { apiInfo, appName, status, releaseTimestamp } = appItems[i];
|
|
551
|
-
if (!apiInfo) {
|
|
552
|
-
continue;
|
|
602
|
+
}) : /* @__PURE__ */ new Map();
|
|
603
|
+
const appItems = [];
|
|
604
|
+
for (let i = 0; i < filteredApps.length; i++) {
|
|
605
|
+
const appAddr = filteredApps[i];
|
|
606
|
+
const config = filteredConfigs[i];
|
|
607
|
+
const apiInfo = appInfos.find(
|
|
608
|
+
(info) => info.address && String(info.address).toLowerCase() === appAddr.toLowerCase()
|
|
609
|
+
);
|
|
610
|
+
const profileName = apiInfo?.profile?.name;
|
|
611
|
+
const localName = getAppName(environment, appAddr);
|
|
612
|
+
const appName = profileName || localName;
|
|
613
|
+
const status = apiInfo?.status || getContractStatusString(config.status);
|
|
614
|
+
const releaseBlockNumber = releaseBlockNumbers.get(appAddr);
|
|
615
|
+
const releaseTimestamp = releaseBlockNumber ? blockTimestamps.get(releaseBlockNumber) : void 0;
|
|
616
|
+
appItems.push({ appAddr, apiInfo, appName, status, releaseTimestamp });
|
|
553
617
|
}
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
showProfile: false
|
|
618
|
+
appItems.sort((a, b) => {
|
|
619
|
+
const aPriority = getStatusSortPriority(a.status);
|
|
620
|
+
const bPriority = getStatusSortPriority(b.status);
|
|
621
|
+
if (aPriority !== bPriority) {
|
|
622
|
+
return aPriority - bPriority;
|
|
623
|
+
}
|
|
624
|
+
const aTime = a.releaseTimestamp || 0;
|
|
625
|
+
const bTime = b.releaseTimestamp || 0;
|
|
626
|
+
return bTime - aTime;
|
|
564
627
|
});
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
628
|
+
console.log();
|
|
629
|
+
this.log(chalk2.bold(`Apps for ${developerAddr} (${environment}):`));
|
|
630
|
+
console.log();
|
|
631
|
+
for (let i = 0; i < appItems.length; i++) {
|
|
632
|
+
const { apiInfo, appName, status, releaseTimestamp } = appItems[i];
|
|
633
|
+
if (!apiInfo) {
|
|
634
|
+
continue;
|
|
635
|
+
}
|
|
636
|
+
const display = formatAppDisplay({
|
|
637
|
+
appInfo: apiInfo,
|
|
638
|
+
appName,
|
|
639
|
+
status,
|
|
640
|
+
releaseTimestamp
|
|
641
|
+
});
|
|
642
|
+
this.log(` ${display.name}`);
|
|
643
|
+
printAppDisplay(display, this.log.bind(this), " ", {
|
|
644
|
+
singleAddress: true,
|
|
645
|
+
showProfile: false
|
|
646
|
+
});
|
|
647
|
+
if (i < appItems.length - 1) {
|
|
648
|
+
this.log(
|
|
649
|
+
chalk2.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")
|
|
650
|
+
);
|
|
651
|
+
}
|
|
569
652
|
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
653
|
+
console.log();
|
|
654
|
+
this.log(chalk2.gray(`Total: ${appItems.length} app(s)`));
|
|
655
|
+
});
|
|
573
656
|
}
|
|
574
657
|
};
|
|
575
658
|
export {
|