@simonfestl/husky-cli 1.25.3 → 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.
@@ -1,50 +1,11 @@
1
1
  import { Command } from "commander";
2
2
  import { getConfig, setSessionConfig, clearSessionConfig, getSessionConfig, fetchAndCacheRole } from "./config.js";
3
3
  import { getPermissions, clearPermissionsCache, getCacheStatus, hasPermission, canAccessKnowledgeBase } from "../lib/permissions-cache.js";
4
- import { apiRequest as hybridApiRequest } from "../lib/api-client.js";
4
+ import { getApiClient } from "../lib/api-client.js";
5
5
  const API_KEY_ROLES = [
6
6
  "admin", "supervisor", "worker", "reviewer", "support",
7
7
  "purchasing", "ops", "e2e_agent", "pr_agent"
8
8
  ];
9
- /**
10
- * Sanitize error messages to prevent sensitive data leakage.
11
- * Truncates long messages and removes potential secrets.
12
- */
13
- function sanitizeErrorMessage(message, maxLength = 200) {
14
- if (!message)
15
- return "Unknown error";
16
- // Remove potential secrets (patterns like API keys, tokens, etc.)
17
- let sanitized = message
18
- .replace(/[a-zA-Z0-9_-]{32,}/g, "[REDACTED]") // Long alphanumeric strings
19
- .replace(/Bearer\s+[^\s]+/gi, "Bearer [REDACTED]") // Bearer tokens
20
- .replace(/key[=:]\s*[^\s,}]+/gi, "key=[REDACTED]"); // key=value patterns
21
- // Truncate if too long
22
- if (sanitized.length > maxLength) {
23
- sanitized = sanitized.substring(0, maxLength) + "...";
24
- }
25
- return sanitized;
26
- }
27
- async function apiRequest(path, options = {}) {
28
- const config = getConfig();
29
- if (!config.apiUrl || !config.apiKey) {
30
- throw new Error("API not configured. Run: husky config set api-url <url> && husky config set api-key <key>");
31
- }
32
- const url = new URL(path, config.apiUrl);
33
- const res = await fetch(url.toString(), {
34
- method: options.method || "GET",
35
- headers: {
36
- "x-api-key": config.apiKey,
37
- "Content-Type": "application/json",
38
- },
39
- body: options.body ? JSON.stringify(options.body) : undefined,
40
- });
41
- if (!res.ok) {
42
- const error = await res.json().catch(() => ({ error: res.statusText }));
43
- const rawMessage = error.message || error.error || `HTTP ${res.status}`;
44
- throw new Error(sanitizeErrorMessage(rawMessage));
45
- }
46
- return res.json();
47
- }
48
9
  export const authCommand = new Command("auth")
49
10
  .description("Manage API keys and authentication");
50
11
  authCommand
@@ -54,8 +15,9 @@ authCommand
54
15
  .option("--json", "Output as JSON")
55
16
  .action(async (options) => {
56
17
  try {
18
+ const api = getApiClient();
57
19
  const query = options.includeRevoked ? "?includeRevoked=true" : "";
58
- const data = await apiRequest(`/api/auth/keys${query}`);
20
+ const data = await api.get(`/api/auth/keys${query}`);
59
21
  if (options.json) {
60
22
  console.log(JSON.stringify(data.keys, null, 2));
61
23
  return;
@@ -111,10 +73,8 @@ authCommand
111
73
  }
112
74
  body.expiresInDays = days;
113
75
  }
114
- const result = await apiRequest("/api/auth/keys", {
115
- method: "POST",
116
- body,
117
- });
76
+ const api = getApiClient();
77
+ const result = await api.post("/api/auth/keys", body);
118
78
  if (options.json) {
119
79
  console.log(JSON.stringify(result, null, 2));
120
80
  return;
@@ -146,7 +106,8 @@ authCommand
146
106
  .option("--json", "Output as JSON")
147
107
  .action(async (id, options) => {
148
108
  try {
149
- const result = await apiRequest(`/api/auth/keys/${id}`, { method: "DELETE" });
109
+ const api = getApiClient();
110
+ const result = await api.delete(`/api/auth/keys/${id}`);
150
111
  if (options.json) {
151
112
  console.log(JSON.stringify(result, null, 2));
152
113
  return;
@@ -165,7 +126,8 @@ authCommand
165
126
  .option("--json", "Output as JSON")
166
127
  .action(async (options) => {
167
128
  try {
168
- const data = await hybridApiRequest("/api/auth/whoami");
129
+ const api = getApiClient();
130
+ const data = await api.get("/api/auth/whoami");
169
131
  if (options.json) {
170
132
  console.log(JSON.stringify(data, null, 2));
171
133
  return;
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const businessCommand: Command;