@tryghost/velo-cli 0.1.2 → 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 +55 -17
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -104,12 +104,26 @@ async function apiRequest(endpoint, options = {}) {
104
104
  }
105
105
  async function verifyToken(token) {
106
106
  const url = `${API_BASE_URL}/cli/verify`;
107
- const response = await fetch(url, {
108
- headers: {
109
- "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
+ };
110
119
  }
111
- });
112
- return response.json();
120
+ return await response.json();
121
+ } catch (error) {
122
+ return {
123
+ valid: false,
124
+ error: error.message
125
+ };
126
+ }
113
127
  }
114
128
 
115
129
  // src/commands/login.ts
@@ -278,11 +292,6 @@ async function browserLogin() {
278
292
  try {
279
293
  const credentials = await credentialsPromise;
280
294
  spinner.stop();
281
- const verification = await verifyToken(credentials.token);
282
- if (!verification.valid) {
283
- console.log(chalk.red("Token verification failed. Please try again."));
284
- return;
285
- }
286
295
  saveCredentials(credentials);
287
296
  console.log(chalk.green(`
288
297
  \u2713 Logged in as ${chalk.bold(credentials.email)}`));
@@ -343,17 +352,46 @@ async function status(options) {
343
352
  endpoint += `&repo=${encodeURIComponent(options.repo)}`;
344
353
  }
345
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;
346
380
  console.log(chalk3.white.bold("Last " + days + " days:"));
347
- console.log(` Total runs: ${chalk3.cyan(metrics.data.total_runs.toLocaleString())}`);
348
- console.log(` Success rate: ${formatRate(metrics.data.success_rate)}`);
349
- 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")}`);
350
384
  console.log();
351
- 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);
352
390
  if (repos.length > 0) {
353
391
  console.log(chalk3.white.bold("Top repos:"));
354
- for (const [repo, data] of repos) {
355
- const shortName = repo.split("/")[1] || repo;
356
- 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);
357
395
  console.log(` ${chalk3.cyan(shortName.padEnd(20))} ${data.total.toString().padStart(5)} runs ${rateStr}`);
358
396
  }
359
397
  console.log();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tryghost/velo-cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "CLI for Velo CI/CD metrics",
5
5
  "type": "module",
6
6
  "bin": {