@simonfestl/husky-cli 1.25.4 → 1.26.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.
@@ -3,6 +3,7 @@ import { readFileSync, writeFileSync, existsSync, mkdirSync, chmodSync } from "f
3
3
  import { join } from "path";
4
4
  import { homedir } from "os";
5
5
  import { ErrorHelpers, errorWithHint, ExplainTopic } from "../lib/error-hints.js";
6
+ import { getApiClient } from "../lib/api-client.js";
6
7
  // Valid agent roles - used for runtime validation
7
8
  const VALID_ROLES = ["admin", "supervisor", "worker", "reviewer", "e2e_agent", "pr_agent", "support", "devops", "purchasing", "ops"];
8
9
  const CONFIG_DIR = join(homedir(), ".husky");
@@ -118,19 +119,14 @@ export async function fetchAndCacheRole() {
118
119
  return {};
119
120
  }
120
121
  try {
121
- const url = new URL("/api/auth/whoami", config.apiUrl);
122
- const res = await fetch(url.toString(), {
123
- headers: { "x-api-key": config.apiKey },
124
- });
125
- if (res.ok) {
126
- const data = await res.json();
127
- // Update config cache
128
- config.role = data.role;
129
- config.permissions = data.permissions;
130
- config.roleLastChecked = new Date().toISOString();
131
- saveConfig(config);
132
- return { role: data.role, permissions: data.permissions };
133
- }
122
+ const api = getApiClient();
123
+ const data = await api.get("/api/auth/whoami");
124
+ // Update config cache
125
+ config.role = data.role;
126
+ config.permissions = data.permissions;
127
+ config.roleLastChecked = new Date().toISOString();
128
+ saveConfig(config);
129
+ return { role: data.role, permissions: data.permissions };
134
130
  }
135
131
  catch {
136
132
  // Ignore fetch errors, return cached or empty
@@ -458,29 +454,9 @@ configCommand
458
454
  }
459
455
  console.log("Testing API connection...");
460
456
  try {
457
+ const api = getApiClient();
461
458
  // First test basic connectivity with /api/tasks
462
- const tasksUrl = new URL("/api/tasks", config.apiUrl);
463
- const apiKey = config.apiKey; // We already checked it's defined above
464
- const tasksRes = await fetch(tasksUrl.toString(), {
465
- headers: { "x-api-key": apiKey },
466
- });
467
- if (!tasksRes.ok) {
468
- if (tasksRes.status === 401) {
469
- console.error(`API connection failed: Unauthorized (HTTP 401)`);
470
- console.error(" Check your API key with: husky config set api-key <key>");
471
- console.error("\nšŸ’” For configuration help: husky explain config");
472
- process.exit(1);
473
- }
474
- else if (tasksRes.status === 403) {
475
- console.error(`API connection failed: Forbidden (HTTP 403)`);
476
- console.error(" Your API key may not have the required permissions");
477
- console.error("\nšŸ’” For configuration help: husky explain config");
478
- process.exit(1);
479
- }
480
- else {
481
- errorWithHint(`API connection failed: HTTP ${tasksRes.status}`, ExplainTopic.CONFIG, "Check your API configuration");
482
- }
483
- }
459
+ await api.get("/api/tasks");
484
460
  console.log(`API connection successful (API URL: ${config.apiUrl})`);
485
461
  // Check if there's an active session
486
462
  const hasActiveSession = isSessionActive();
@@ -494,12 +470,8 @@ configCommand
494
470
  }
495
471
  else {
496
472
  // No session - fetch API key role from whoami
497
- const whoamiUrl = new URL("/api/auth/whoami", config.apiUrl);
498
- const whoamiRes = await fetch(whoamiUrl.toString(), {
499
- headers: { "x-api-key": apiKey },
500
- });
501
- if (whoamiRes.ok) {
502
- const data = await whoamiRes.json();
473
+ try {
474
+ const data = await api.get("/api/auth/whoami");
503
475
  // Cache the role/permissions (only if no session)
504
476
  const updatedConfig = getConfig();
505
477
  updatedConfig.role = data.role;
@@ -515,17 +487,33 @@ configCommand
515
487
  console.log(` Agent ID: ${data.agentId}`);
516
488
  }
517
489
  }
490
+ catch {
491
+ // whoami failed, but tasks worked - connection is fine
492
+ }
518
493
  }
519
494
  }
520
495
  catch (error) {
521
- if (error instanceof TypeError && error.message.includes("fetch")) {
496
+ const errorMsg = error instanceof Error ? error.message : "Unknown error";
497
+ if (errorMsg.includes("401")) {
498
+ console.error(`API connection failed: Unauthorized (HTTP 401)`);
499
+ console.error(" Check your API key with: husky config set api-key <key>");
500
+ console.error("\n For configuration help: husky explain config");
501
+ process.exit(1);
502
+ }
503
+ else if (errorMsg.includes("403")) {
504
+ console.error(`API connection failed: Forbidden (HTTP 403)`);
505
+ console.error(" Your API key may not have the required permissions");
506
+ console.error("\n For configuration help: husky explain config");
507
+ process.exit(1);
508
+ }
509
+ else if (error instanceof TypeError && errorMsg.includes("fetch")) {
522
510
  console.error(`API connection failed: Could not connect to ${config.apiUrl}`);
523
511
  console.error(" Check your API URL with: husky config set api-url <url>");
524
- console.error("\nšŸ’” For configuration help: husky explain config");
512
+ console.error("\n For configuration help: husky explain config");
525
513
  }
526
514
  else {
527
- console.error(`API connection failed: ${error instanceof Error ? error.message : "Unknown error"}`);
528
- console.error("\nšŸ’” For configuration help: husky explain config");
515
+ console.error(`API connection failed: ${errorMsg}`);
516
+ console.error("\n For configuration help: husky explain config");
529
517
  }
530
518
  process.exit(1);
531
519
  }