@eve-horizon/cli 0.2.38 → 0.2.40
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/dist/index.js +220 -39
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9811,8 +9811,8 @@ var require_sync = __commonJS({
|
|
|
9811
9811
|
}
|
|
9812
9812
|
return x;
|
|
9813
9813
|
};
|
|
9814
|
-
var defaultReadPackageSync = function defaultReadPackageSync2(
|
|
9815
|
-
var body =
|
|
9814
|
+
var defaultReadPackageSync = function defaultReadPackageSync2(readFileSync25, pkgfile) {
|
|
9815
|
+
var body = readFileSync25(pkgfile);
|
|
9816
9816
|
try {
|
|
9817
9817
|
var pkg = JSON.parse(body);
|
|
9818
9818
|
return pkg;
|
|
@@ -9832,7 +9832,7 @@ var require_sync = __commonJS({
|
|
|
9832
9832
|
}
|
|
9833
9833
|
var opts = normalizeOptions(x, options);
|
|
9834
9834
|
var isFile = opts.isFile || defaultIsFile;
|
|
9835
|
-
var
|
|
9835
|
+
var readFileSync25 = opts.readFileSync || fs6.readFileSync;
|
|
9836
9836
|
var isDirectory = opts.isDirectory || defaultIsDir;
|
|
9837
9837
|
var realpathSync = opts.realpathSync || defaultRealpathSync;
|
|
9838
9838
|
var readPackageSync = opts.readPackageSync || defaultReadPackageSync;
|
|
@@ -9889,7 +9889,7 @@ var require_sync = __commonJS({
|
|
|
9889
9889
|
if (!isFile(pkgfile)) {
|
|
9890
9890
|
return loadpkg(path8.dirname(dir));
|
|
9891
9891
|
}
|
|
9892
|
-
var pkg = readPackageSync(
|
|
9892
|
+
var pkg = readPackageSync(readFileSync25, pkgfile);
|
|
9893
9893
|
if (pkg && opts.packageFilter) {
|
|
9894
9894
|
pkg = opts.packageFilter(
|
|
9895
9895
|
pkg,
|
|
@@ -9903,7 +9903,7 @@ var require_sync = __commonJS({
|
|
|
9903
9903
|
var pkgfile = path8.join(maybeRealpathSync(realpathSync, x2, opts), "/package.json");
|
|
9904
9904
|
if (isFile(pkgfile)) {
|
|
9905
9905
|
try {
|
|
9906
|
-
var pkg = readPackageSync(
|
|
9906
|
+
var pkg = readPackageSync(readFileSync25, pkgfile);
|
|
9907
9907
|
} catch (e) {
|
|
9908
9908
|
}
|
|
9909
9909
|
if (pkg && opts.packageFilter) {
|
|
@@ -48552,6 +48552,10 @@ var require_src57 = __commonJS({
|
|
|
48552
48552
|
}
|
|
48553
48553
|
});
|
|
48554
48554
|
|
|
48555
|
+
// src/index.ts
|
|
48556
|
+
var import_fs4 = require("fs");
|
|
48557
|
+
var import_path3 = require("path");
|
|
48558
|
+
|
|
48555
48559
|
// src/lib/args.ts
|
|
48556
48560
|
function parseArgs(args) {
|
|
48557
48561
|
const flags = {};
|
|
@@ -48648,7 +48652,7 @@ var import_node_fs2 = require("node:fs");
|
|
|
48648
48652
|
var import_node_path2 = require("node:path");
|
|
48649
48653
|
var import_yaml = require("yaml");
|
|
48650
48654
|
var DEFAULT_PROFILE = "default";
|
|
48651
|
-
var DEFAULT_API_URL = "
|
|
48655
|
+
var DEFAULT_API_URL = "https://api.eh1.incept5.dev";
|
|
48652
48656
|
function getRepoProfilePath() {
|
|
48653
48657
|
return (0, import_node_path2.join)(process.cwd(), ".eve", "profile.yaml");
|
|
48654
48658
|
}
|
|
@@ -49522,7 +49526,7 @@ for cloud deployments. Credentials are stored globally per API URL.`,
|
|
|
49522
49526
|
options: [
|
|
49523
49527
|
"--email <email> Email address for SSH login (uses profile default_email if not provided)",
|
|
49524
49528
|
"--user-id <id> User id for SSH login",
|
|
49525
|
-
"--ssh-key <path> Path to SSH private key (
|
|
49529
|
+
"--ssh-key <path> Path to SSH private key (auto-discovers from ~/.ssh/ if omitted)",
|
|
49526
49530
|
"--ttl <days> Token TTL in days (1-90, default: server configured)",
|
|
49527
49531
|
"--password <pass> Supabase password (triggers Supabase login)",
|
|
49528
49532
|
"--supabase-url <url> Supabase URL",
|
|
@@ -51553,6 +51557,22 @@ async function requestRaw(context2, path8, options = {}) {
|
|
|
51553
51557
|
body: options.body ? JSON.stringify(options.body) : void 0
|
|
51554
51558
|
});
|
|
51555
51559
|
} catch (error) {
|
|
51560
|
+
const cause = error instanceof Error ? error.cause : void 0;
|
|
51561
|
+
const code = cause?.code;
|
|
51562
|
+
const isConnectionError = code === "ECONNREFUSED" || code === "ENOTFOUND" || code === "ETIMEDOUT" || error instanceof Error && error.message.includes("fetch failed");
|
|
51563
|
+
if (isConnectionError) {
|
|
51564
|
+
throw new Error(
|
|
51565
|
+
`Could not connect to ${context2.apiUrl}
|
|
51566
|
+
|
|
51567
|
+
The API is unreachable. Check that:
|
|
51568
|
+
- The URL is correct (current: ${context2.apiUrl})
|
|
51569
|
+
- Your internet connection is working
|
|
51570
|
+
|
|
51571
|
+
To change the API URL:
|
|
51572
|
+
eve profile set default --api-url <url>
|
|
51573
|
+
or set EVE_API_URL=<url>`
|
|
51574
|
+
);
|
|
51575
|
+
}
|
|
51556
51576
|
const message = error instanceof Error ? error.message : String(error);
|
|
51557
51577
|
throw new Error(`Request failed for ${method} ${url}: ${message}`);
|
|
51558
51578
|
}
|
|
@@ -62200,7 +62220,7 @@ var import_child_process = require("child_process");
|
|
|
62200
62220
|
var import_util4 = require("util");
|
|
62201
62221
|
var execFileAsync = (0, import_util4.promisify)(import_child_process.execFile);
|
|
62202
62222
|
|
|
62203
|
-
//
|
|
62223
|
+
// ../shared/dist/log-normalize.js
|
|
62204
62224
|
function normalizeLogLine(line) {
|
|
62205
62225
|
const kind = line.kind;
|
|
62206
62226
|
const raw = line.raw;
|
|
@@ -66153,6 +66173,41 @@ function pickFreshestCodeAuth() {
|
|
|
66153
66173
|
if (candidates.length === 0) return null;
|
|
66154
66174
|
return candidates.reduce((best, c) => c.expiresAt > best.expiresAt ? c : best);
|
|
66155
66175
|
}
|
|
66176
|
+
var SSH_KEY_IGNORE = /* @__PURE__ */ new Set([
|
|
66177
|
+
"config",
|
|
66178
|
+
"known_hosts",
|
|
66179
|
+
"known_hosts.old",
|
|
66180
|
+
"authorized_keys",
|
|
66181
|
+
"environment"
|
|
66182
|
+
]);
|
|
66183
|
+
var SSH_KEY_PRIORITY = {
|
|
66184
|
+
id_ed25519: 0,
|
|
66185
|
+
id_ecdsa: 1,
|
|
66186
|
+
id_rsa: 2
|
|
66187
|
+
};
|
|
66188
|
+
function discoverSshKeys() {
|
|
66189
|
+
const sshDir = (0, import_node_path5.join)((0, import_node_os3.homedir)(), ".ssh");
|
|
66190
|
+
if (!(0, import_node_fs5.existsSync)(sshDir)) return [];
|
|
66191
|
+
let entries;
|
|
66192
|
+
try {
|
|
66193
|
+
entries = (0, import_node_fs5.readdirSync)(sshDir);
|
|
66194
|
+
} catch {
|
|
66195
|
+
return [];
|
|
66196
|
+
}
|
|
66197
|
+
const candidates = [];
|
|
66198
|
+
for (const name of entries) {
|
|
66199
|
+
if (name.startsWith(".")) continue;
|
|
66200
|
+
if (name.endsWith(".pub")) continue;
|
|
66201
|
+
if (SSH_KEY_IGNORE.has(name)) continue;
|
|
66202
|
+
if (!name.startsWith("id_") && !name.includes("key")) continue;
|
|
66203
|
+
const fullPath = (0, import_node_path5.join)(sshDir, name);
|
|
66204
|
+
const pubPath = `${fullPath}.pub`;
|
|
66205
|
+
if (!(0, import_node_fs5.existsSync)(pubPath)) continue;
|
|
66206
|
+
const priority = SSH_KEY_PRIORITY[name] ?? 10;
|
|
66207
|
+
candidates.push({ path: fullPath, priority });
|
|
66208
|
+
}
|
|
66209
|
+
return candidates.sort((a, b2) => a.priority - b2.priority).map((c) => c.path);
|
|
66210
|
+
}
|
|
66156
66211
|
function signNonceWithSsh(keyPath, nonce) {
|
|
66157
66212
|
const tempDir = (0, import_node_fs5.mkdtempSync)((0, import_node_path5.join)((0, import_node_os3.tmpdir)(), "eve-auth-"));
|
|
66158
66213
|
const noncePath = (0, import_node_path5.join)(tempDir, "nonce");
|
|
@@ -66171,12 +66226,17 @@ function signNonceWithSsh(keyPath, nonce) {
|
|
|
66171
66226
|
}
|
|
66172
66227
|
}
|
|
66173
66228
|
async function attemptSshLogin(context2, credentials, flags, email, userId, ttlDays) {
|
|
66229
|
+
const explicitKey = getStringFlag(flags, ["ssh-key"]) || process.env.EVE_AUTH_SSH_KEY || context2.profile.default_ssh_key;
|
|
66230
|
+
const keysToTry = explicitKey ? [explicitKey] : discoverSshKeys();
|
|
66231
|
+
if (keysToTry.length === 0) {
|
|
66232
|
+
return {
|
|
66233
|
+
success: false,
|
|
66234
|
+
error: "No SSH keys found. Provide --ssh-key <path> or add a keypair to ~/.ssh/"
|
|
66235
|
+
};
|
|
66236
|
+
}
|
|
66174
66237
|
const challengeResponse = await requestRaw(context2, "/auth/challenge", {
|
|
66175
66238
|
method: "POST",
|
|
66176
|
-
body: {
|
|
66177
|
-
email,
|
|
66178
|
-
user_id: userId
|
|
66179
|
-
}
|
|
66239
|
+
body: { email, user_id: userId }
|
|
66180
66240
|
});
|
|
66181
66241
|
if (!challengeResponse.ok) {
|
|
66182
66242
|
const message = typeof challengeResponse.data === "string" ? challengeResponse.data : challengeResponse.text;
|
|
@@ -66186,33 +66246,42 @@ async function attemptSshLogin(context2, credentials, flags, email, userId, ttlD
|
|
|
66186
66246
|
if (!challenge.challenge_id || !challenge.nonce) {
|
|
66187
66247
|
return { success: false, error: "Challenge response missing fields" };
|
|
66188
66248
|
}
|
|
66189
|
-
|
|
66190
|
-
|
|
66191
|
-
|
|
66192
|
-
|
|
66193
|
-
|
|
66194
|
-
|
|
66195
|
-
|
|
66196
|
-
|
|
66197
|
-
|
|
66198
|
-
|
|
66199
|
-
|
|
66200
|
-
|
|
66201
|
-
|
|
66202
|
-
|
|
66203
|
-
|
|
66204
|
-
|
|
66205
|
-
|
|
66206
|
-
|
|
66207
|
-
|
|
66249
|
+
let lastError = "";
|
|
66250
|
+
for (const keyPath of keysToTry) {
|
|
66251
|
+
let signature;
|
|
66252
|
+
try {
|
|
66253
|
+
signature = signNonceWithSsh(keyPath, challenge.nonce);
|
|
66254
|
+
} catch {
|
|
66255
|
+
continue;
|
|
66256
|
+
}
|
|
66257
|
+
const verifyResponse = await requestRaw(context2, "/auth/verify", {
|
|
66258
|
+
method: "POST",
|
|
66259
|
+
body: {
|
|
66260
|
+
challenge_id: challenge.challenge_id,
|
|
66261
|
+
signature,
|
|
66262
|
+
...ttlDays !== void 0 && { ttl_days: ttlDays }
|
|
66263
|
+
}
|
|
66264
|
+
});
|
|
66265
|
+
if (verifyResponse.ok) {
|
|
66266
|
+
const payload = verifyResponse.data;
|
|
66267
|
+
if (!payload.access_token) {
|
|
66268
|
+
return { success: false, error: "Auth verify response missing access_token" };
|
|
66269
|
+
}
|
|
66270
|
+
credentials.tokens[context2.authKey] = {
|
|
66271
|
+
access_token: payload.access_token,
|
|
66272
|
+
expires_at: payload.expires_at,
|
|
66273
|
+
token_type: payload.token_type
|
|
66274
|
+
};
|
|
66275
|
+
saveCredentials(credentials);
|
|
66276
|
+
if (!explicitKey) {
|
|
66277
|
+
const shortPath = keyPath.replace((0, import_node_os3.homedir)(), "~");
|
|
66278
|
+
console.log(`Using SSH key: ${shortPath}`);
|
|
66279
|
+
}
|
|
66280
|
+
return { success: true, tokenType: payload.token_type };
|
|
66281
|
+
}
|
|
66282
|
+
lastError = typeof verifyResponse.data === "string" ? verifyResponse.data : verifyResponse.text;
|
|
66208
66283
|
}
|
|
66209
|
-
|
|
66210
|
-
access_token: payload.access_token,
|
|
66211
|
-
expires_at: payload.expires_at,
|
|
66212
|
-
token_type: payload.token_type
|
|
66213
|
-
};
|
|
66214
|
-
saveCredentials(credentials);
|
|
66215
|
-
return { success: true, tokenType: payload.token_type };
|
|
66284
|
+
return { success: false, error: `Auth verify failed: ${lastError}` };
|
|
66216
66285
|
}
|
|
66217
66286
|
async function fetchGitHubKeys(username) {
|
|
66218
66287
|
const response = await fetch(`https://github.com/${username}.keys`);
|
|
@@ -73349,6 +73418,9 @@ var import_node_fs10 = require("node:fs");
|
|
|
73349
73418
|
async function handleAdmin(subcommand, positionals, flags, context2) {
|
|
73350
73419
|
const json = Boolean(flags.json);
|
|
73351
73420
|
switch (subcommand) {
|
|
73421
|
+
case "users": {
|
|
73422
|
+
return handleUsers(flags, context2, json);
|
|
73423
|
+
}
|
|
73352
73424
|
case "invite": {
|
|
73353
73425
|
const githubUsername = getStringFlag(flags, ["github"]);
|
|
73354
73426
|
const sshKeyPath = getStringFlag(flags, ["ssh-key"]);
|
|
@@ -73834,8 +73906,68 @@ ${rows.length} alias(es)`);
|
|
|
73834
73906
|
}
|
|
73835
73907
|
}
|
|
73836
73908
|
default:
|
|
73837
|
-
throw new Error("Usage: eve admin <invite|pricing|receipts|balance|usage|ingress-aliases|access-requests>");
|
|
73909
|
+
throw new Error("Usage: eve admin <users|invite|pricing|receipts|balance|usage|ingress-aliases|access-requests>");
|
|
73910
|
+
}
|
|
73911
|
+
}
|
|
73912
|
+
async function handleUsers(flags, context2, json) {
|
|
73913
|
+
const users = await requestJson(context2, "/system/users");
|
|
73914
|
+
if (json) {
|
|
73915
|
+
outputJson(users, true);
|
|
73916
|
+
return;
|
|
73917
|
+
}
|
|
73918
|
+
if (users.length === 0) {
|
|
73919
|
+
console.log("No users found.");
|
|
73920
|
+
return;
|
|
73921
|
+
}
|
|
73922
|
+
const rows = [];
|
|
73923
|
+
for (const user of users) {
|
|
73924
|
+
const base = {
|
|
73925
|
+
id: user.id,
|
|
73926
|
+
email: user.email,
|
|
73927
|
+
name: user.display_name ?? "-",
|
|
73928
|
+
admin: user.is_admin ? "yes" : "",
|
|
73929
|
+
created: user.created_at?.split("T")[0] ?? ""
|
|
73930
|
+
};
|
|
73931
|
+
if (user.memberships.length === 0) {
|
|
73932
|
+
rows.push({ ...base, org: "-", role: "-" });
|
|
73933
|
+
} else {
|
|
73934
|
+
for (const m of user.memberships) {
|
|
73935
|
+
rows.push({ ...base, org: m.org_slug || m.org_name, role: m.role });
|
|
73936
|
+
}
|
|
73937
|
+
}
|
|
73938
|
+
}
|
|
73939
|
+
const col = (key, header2) => Math.max(header2.length, ...rows.map((r) => r[key].length));
|
|
73940
|
+
const w = {
|
|
73941
|
+
email: col("email", "Email"),
|
|
73942
|
+
name: col("name", "Name"),
|
|
73943
|
+
admin: col("admin", "Admin"),
|
|
73944
|
+
org: col("org", "Org"),
|
|
73945
|
+
role: col("role", "Role"),
|
|
73946
|
+
created: col("created", "Created")
|
|
73947
|
+
};
|
|
73948
|
+
const pad3 = (s, n) => s + " ".repeat(Math.max(0, n - s.length));
|
|
73949
|
+
const header = [
|
|
73950
|
+
pad3("Email", w.email),
|
|
73951
|
+
pad3("Name", w.name),
|
|
73952
|
+
pad3("Admin", w.admin),
|
|
73953
|
+
pad3("Org", w.org),
|
|
73954
|
+
pad3("Role", w.role),
|
|
73955
|
+
pad3("Created", w.created)
|
|
73956
|
+
].join(" ");
|
|
73957
|
+
console.log(header);
|
|
73958
|
+
console.log("-".repeat(header.length));
|
|
73959
|
+
for (const row of rows) {
|
|
73960
|
+
console.log([
|
|
73961
|
+
pad3(row.email, w.email),
|
|
73962
|
+
pad3(row.name, w.name),
|
|
73963
|
+
pad3(row.admin, w.admin),
|
|
73964
|
+
pad3(row.org, w.org),
|
|
73965
|
+
pad3(row.role, w.role),
|
|
73966
|
+
pad3(row.created, w.created)
|
|
73967
|
+
].join(" "));
|
|
73838
73968
|
}
|
|
73969
|
+
console.log("");
|
|
73970
|
+
console.log(`${users.length} user(s)`);
|
|
73839
73971
|
}
|
|
73840
73972
|
function formatBalanceSummary(data) {
|
|
73841
73973
|
if (!data.currency) {
|
|
@@ -80498,11 +80630,60 @@ function sleep(ms) {
|
|
|
80498
80630
|
}
|
|
80499
80631
|
|
|
80500
80632
|
// src/index.ts
|
|
80633
|
+
function getCliVersion() {
|
|
80634
|
+
try {
|
|
80635
|
+
const pkg = JSON.parse((0, import_fs4.readFileSync)((0, import_path3.join)(__dirname, "..", "package.json"), "utf-8"));
|
|
80636
|
+
return pkg.version;
|
|
80637
|
+
} catch {
|
|
80638
|
+
return "unknown";
|
|
80639
|
+
}
|
|
80640
|
+
}
|
|
80641
|
+
async function showVersion(json, apiUrl) {
|
|
80642
|
+
const cliVersion = getCliVersion();
|
|
80643
|
+
let platformInfo = null;
|
|
80644
|
+
if (apiUrl) {
|
|
80645
|
+
try {
|
|
80646
|
+
const res = await fetch(`${apiUrl}/health/version`);
|
|
80647
|
+
if (res.ok) {
|
|
80648
|
+
platformInfo = await res.json();
|
|
80649
|
+
}
|
|
80650
|
+
} catch {
|
|
80651
|
+
}
|
|
80652
|
+
}
|
|
80653
|
+
if (json) {
|
|
80654
|
+
const result = { cli: cliVersion };
|
|
80655
|
+
if (platformInfo) {
|
|
80656
|
+
result.platform = platformInfo;
|
|
80657
|
+
}
|
|
80658
|
+
if (apiUrl) {
|
|
80659
|
+
result.apiUrl = apiUrl;
|
|
80660
|
+
}
|
|
80661
|
+
console.log(JSON.stringify(result, null, 2));
|
|
80662
|
+
} else {
|
|
80663
|
+
console.log(`eve v${cliVersion}`);
|
|
80664
|
+
if (platformInfo) {
|
|
80665
|
+
const sha = platformInfo.gitSha !== "unknown" ? ` (${platformInfo.gitSha.slice(0, 7)})` : "";
|
|
80666
|
+
console.log(`platform v${platformInfo.version}${sha}`);
|
|
80667
|
+
}
|
|
80668
|
+
}
|
|
80669
|
+
}
|
|
80501
80670
|
async function main2() {
|
|
80502
80671
|
const { flags, positionals } = parseArgs(process.argv.slice(2));
|
|
80503
80672
|
const command = positionals[0];
|
|
80504
80673
|
const subcommand = positionals[1];
|
|
80505
80674
|
const rest = positionals.slice(2);
|
|
80675
|
+
if (flags.version || command === "-v" || command === "version") {
|
|
80676
|
+
const json = Boolean(flags.json);
|
|
80677
|
+
let apiUrl;
|
|
80678
|
+
try {
|
|
80679
|
+
const credentials2 = loadCredentials();
|
|
80680
|
+
const context3 = resolveContext(flags, credentials2);
|
|
80681
|
+
apiUrl = context3.apiUrl;
|
|
80682
|
+
} catch {
|
|
80683
|
+
}
|
|
80684
|
+
await showVersion(json, apiUrl);
|
|
80685
|
+
return;
|
|
80686
|
+
}
|
|
80506
80687
|
if (!command || command === "-h" || command === "--help") {
|
|
80507
80688
|
showMainHelp();
|
|
80508
80689
|
return;
|