@tryghost/velo-cli 0.1.1 → 0.1.4

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 (2) hide show
  1. package/dist/index.js +61 -18
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -8,6 +8,9 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
8
8
 
9
9
  // src/index.ts
10
10
  import { Command } from "commander";
11
+ import { readFileSync as readFileSync2 } from "fs";
12
+ import { fileURLToPath } from "url";
13
+ import { dirname, join as join2 } from "path";
11
14
 
12
15
  // src/commands/login.ts
13
16
  import { createServer } from "http";
@@ -101,12 +104,26 @@ async function apiRequest(endpoint, options = {}) {
101
104
  }
102
105
  async function verifyToken(token) {
103
106
  const url = `${API_BASE_URL}/cli/verify`;
104
- const response = await fetch(url, {
105
- headers: {
106
- "Authorization": `Bearer ${token}`
107
+ try {
108
+ const response = await fetch(url, {
109
+ headers: {
110
+ "Authorization": `Bearer ${token}`
111
+ }
112
+ });
113
+ const contentType = response.headers.get("content-type") || "";
114
+ if (contentType.includes("text/html")) {
115
+ return {
116
+ valid: false,
117
+ error: "Authentication required (got HTML instead of JSON - endpoint may be behind Cloudflare Access)"
118
+ };
107
119
  }
108
- });
109
- return response.json();
120
+ return await response.json();
121
+ } catch (error) {
122
+ return {
123
+ valid: false,
124
+ error: error.message
125
+ };
126
+ }
110
127
  }
111
128
 
112
129
  // src/commands/login.ts
@@ -275,11 +292,6 @@ async function browserLogin() {
275
292
  try {
276
293
  const credentials = await credentialsPromise;
277
294
  spinner.stop();
278
- const verification = await verifyToken(credentials.token);
279
- if (!verification.valid) {
280
- console.log(chalk.red("Token verification failed. Please try again."));
281
- return;
282
- }
283
295
  saveCredentials(credentials);
284
296
  console.log(chalk.green(`
285
297
  \u2713 Logged in as ${chalk.bold(credentials.email)}`));
@@ -340,17 +352,46 @@ async function status(options) {
340
352
  endpoint += `&repo=${encodeURIComponent(options.repo)}`;
341
353
  }
342
354
  const metrics = await apiRequest(endpoint);
355
+ const repoStats = {};
356
+ let totalRuns = 0;
357
+ let totalSuccesses = 0;
358
+ let totalDurationMs = 0;
359
+ let durationCount = 0;
360
+ for (const item of metrics.summary) {
361
+ const count = parseInt(item.count, 10);
362
+ totalRuns += count;
363
+ if (!repoStats[item.repo]) {
364
+ repoStats[item.repo] = { total: 0, successes: 0, failures: 0, totalDurationMs: 0, successCount: 0 };
365
+ }
366
+ repoStats[item.repo].total += count;
367
+ if (item.status === "success") {
368
+ totalSuccesses += count;
369
+ repoStats[item.repo].successes += count;
370
+ repoStats[item.repo].totalDurationMs += item.avg_duration_ms * count;
371
+ repoStats[item.repo].successCount += count;
372
+ totalDurationMs += item.avg_duration_ms * count;
373
+ durationCount += count;
374
+ } else if (item.status === "failure") {
375
+ repoStats[item.repo].failures += count;
376
+ }
377
+ }
378
+ const successRate = totalRuns > 0 ? totalSuccesses / totalRuns * 100 : 0;
379
+ const avgDurationMin = durationCount > 0 ? totalDurationMs / durationCount / 6e4 : 0;
343
380
  console.log(chalk3.white.bold("Last " + days + " days:"));
344
- console.log(` Total runs: ${chalk3.cyan(metrics.data.total_runs.toLocaleString())}`);
345
- console.log(` Success rate: ${formatRate(metrics.data.success_rate)}`);
346
- console.log(` Avg duration: ${chalk3.gray(metrics.data.avg_duration_minutes.toFixed(1) + " min")}`);
381
+ console.log(` Total runs: ${chalk3.cyan(totalRuns.toLocaleString())}`);
382
+ console.log(` Success rate: ${formatRate(successRate)}`);
383
+ console.log(` Avg duration: ${chalk3.gray(avgDurationMin.toFixed(1) + " min")}`);
347
384
  console.log();
348
- const repos = Object.entries(metrics.data.by_repo).sort((a, b) => b[1].total - a[1].total).slice(0, 5);
385
+ const repos = Object.entries(repoStats).map(([repo, data]) => ({
386
+ repo,
387
+ ...data,
388
+ successRate: data.total > 0 ? data.successes / data.total * 100 : 0
389
+ })).sort((a, b) => b.total - a.total).slice(0, 5);
349
390
  if (repos.length > 0) {
350
391
  console.log(chalk3.white.bold("Top repos:"));
351
- for (const [repo, data] of repos) {
352
- const shortName = repo.split("/")[1] || repo;
353
- const rateStr = formatRate(data.success_rate);
392
+ for (const data of repos) {
393
+ const shortName = data.repo.split("/")[1] || data.repo;
394
+ const rateStr = formatRate(data.successRate);
354
395
  console.log(` ${chalk3.cyan(shortName.padEnd(20))} ${data.total.toString().padStart(5)} runs ${rateStr}`);
355
396
  }
356
397
  console.log();
@@ -446,8 +487,10 @@ async function api(endpoint, options) {
446
487
  }
447
488
 
448
489
  // src/index.ts
490
+ var __dirname = dirname(fileURLToPath(import.meta.url));
491
+ var pkg = JSON.parse(readFileSync2(join2(__dirname, "..", "package.json"), "utf-8"));
449
492
  var program = new Command();
450
- program.name("velo").description("CLI for Velo CI/CD metrics").version("0.1.0");
493
+ program.name("velo").description("CLI for Velo CI/CD metrics").version(pkg.version);
451
494
  program.command("login").description("Authenticate via Ghost SSO").option("--manual", "Use manual token entry (for headless servers)").action((options) => login({ manual: options.manual }));
452
495
  program.command("logout").description("Clear saved credentials").action(logout);
453
496
  program.command("status").description("Show CI health overview").option("-r, --repo <repo>", "Filter by repository (e.g., TryGhost/Ghost)").option("-d, --days <days>", "Number of days to analyze (default: 7)", "7").action((options) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tryghost/velo-cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.4",
4
4
  "description": "CLI for Velo CI/CD metrics",
5
5
  "type": "module",
6
6
  "bin": {