refactor: improve code formatting and readability across multiple files
This commit is contained in:
parent
c5acc63129
commit
cb8c45456b
6 changed files with 79 additions and 42 deletions
|
|
@ -74,7 +74,10 @@ import ElicitationTab, {
|
|||
PendingElicitationRequest,
|
||||
ElicitationResponse,
|
||||
} from "./components/ElicitationTab";
|
||||
import { CustomHeaders, migrateFromLegacyAuth } from "./lib/types/customHeaders";
|
||||
import {
|
||||
CustomHeaders,
|
||||
migrateFromLegacyAuth,
|
||||
} from "./lib/types/customHeaders";
|
||||
|
||||
const CONFIG_LOCAL_STORAGE_KEY = "inspectorConfig_v1";
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,11 @@ import { Input } from "@/components/ui/input";
|
|||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Plus, Trash2, Eye, EyeOff } from "lucide-react";
|
||||
import { CustomHeaders as CustomHeadersType, CustomHeader, createEmptyHeader } from "@/lib/types/customHeaders";
|
||||
import {
|
||||
CustomHeaders as CustomHeadersType,
|
||||
CustomHeader,
|
||||
createEmptyHeader,
|
||||
} from "@/lib/types/customHeaders";
|
||||
|
||||
interface CustomHeadersProps {
|
||||
headers: CustomHeadersType;
|
||||
|
|
@ -12,13 +16,21 @@ interface CustomHeadersProps {
|
|||
className?: string;
|
||||
}
|
||||
|
||||
const CustomHeaders = ({ headers, onChange, className }: CustomHeadersProps) => {
|
||||
const CustomHeaders = ({
|
||||
headers,
|
||||
onChange,
|
||||
className,
|
||||
}: CustomHeadersProps) => {
|
||||
const [isJsonMode, setIsJsonMode] = useState(false);
|
||||
const [jsonValue, setJsonValue] = useState("");
|
||||
const [jsonError, setJsonError] = useState<string | null>(null);
|
||||
const [visibleValues, setVisibleValues] = useState<Set<number>>(new Set());
|
||||
|
||||
const updateHeader = (index: number, field: keyof CustomHeader, value: string | boolean) => {
|
||||
const updateHeader = (
|
||||
index: number,
|
||||
field: keyof CustomHeader,
|
||||
value: string | boolean,
|
||||
) => {
|
||||
const newHeaders = [...headers];
|
||||
newHeaders[index] = { ...newHeaders[index], [field]: value };
|
||||
onChange(newHeaders);
|
||||
|
|
@ -58,16 +70,22 @@ const CustomHeaders = ({ headers, onChange, className }: CustomHeadersProps) =>
|
|||
const switchToFormMode = () => {
|
||||
try {
|
||||
const parsed = JSON.parse(jsonValue);
|
||||
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
||||
if (
|
||||
typeof parsed !== "object" ||
|
||||
parsed === null ||
|
||||
Array.isArray(parsed)
|
||||
) {
|
||||
setJsonError("JSON must be an object with string key-value pairs");
|
||||
return;
|
||||
}
|
||||
|
||||
const newHeaders: CustomHeadersType = Object.entries(parsed).map(([name, value]) => ({
|
||||
name,
|
||||
value: String(value),
|
||||
enabled: true,
|
||||
}));
|
||||
const newHeaders: CustomHeadersType = Object.entries(parsed).map(
|
||||
([name, value]) => ({
|
||||
name,
|
||||
value: String(value),
|
||||
enabled: true,
|
||||
}),
|
||||
);
|
||||
|
||||
onChange(newHeaders);
|
||||
setJsonError(null);
|
||||
|
|
@ -86,7 +104,9 @@ const CustomHeaders = ({ headers, onChange, className }: CustomHeadersProps) =>
|
|||
return (
|
||||
<div className={`space-y-3 ${className}`}>
|
||||
<div className="flex justify-between items-center gap-2">
|
||||
<h4 className="text-sm font-semibold flex-shrink-0">Custom Headers (JSON)</h4>
|
||||
<h4 className="text-sm font-semibold flex-shrink-0">
|
||||
Custom Headers (JSON)
|
||||
</h4>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
|
|
@ -104,9 +124,7 @@ const CustomHeaders = ({ headers, onChange, className }: CustomHeadersProps) =>
|
|||
placeholder='{\n "Authorization": "Bearer token123",\n "X-Tenant-ID": "acme-inc",\n "X-Environment": "staging"\n}'
|
||||
className="font-mono text-sm min-h-[100px] resize-none"
|
||||
/>
|
||||
{jsonError && (
|
||||
<p className="text-sm text-red-600">{jsonError}</p>
|
||||
)}
|
||||
{jsonError && <p className="text-sm text-red-600">{jsonError}</p>}
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Enter headers as a JSON object with string key-value pairs.
|
||||
</p>
|
||||
|
|
@ -156,7 +174,9 @@ const CustomHeaders = ({ headers, onChange, className }: CustomHeadersProps) =>
|
|||
>
|
||||
<Switch
|
||||
checked={header.enabled}
|
||||
onCheckedChange={(enabled) => updateHeader(index, "enabled", enabled)}
|
||||
onCheckedChange={(enabled) =>
|
||||
updateHeader(index, "enabled", enabled)
|
||||
}
|
||||
className="shrink-0 mt-2"
|
||||
/>
|
||||
<div className="flex-1 min-w-0 space-y-2">
|
||||
|
|
@ -170,7 +190,9 @@ const CustomHeaders = ({ headers, onChange, className }: CustomHeadersProps) =>
|
|||
<Input
|
||||
placeholder="Header Value"
|
||||
value={header.value}
|
||||
onChange={(e) => updateHeader(index, "value", e.target.value)}
|
||||
onChange={(e) =>
|
||||
updateHeader(index, "value", e.target.value)
|
||||
}
|
||||
type={visibleValues.has(index) ? "text" : "password"}
|
||||
className="font-mono text-xs pr-8"
|
||||
/>
|
||||
|
|
@ -205,7 +227,8 @@ const CustomHeaders = ({ headers, onChange, className }: CustomHeadersProps) =>
|
|||
|
||||
{headers.length > 0 && (
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Use the toggle to enable/disable headers. Only enabled headers with both name and value will be sent.
|
||||
Use the toggle to enable/disable headers. Only enabled headers with
|
||||
both name and value will be sent.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,14 +10,14 @@ const Switch = React.forwardRef<
|
|||
<SwitchPrimitives.Root
|
||||
className={cn(
|
||||
"peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
ref={ref}
|
||||
>
|
||||
<SwitchPrimitives.Thumb
|
||||
className={cn(
|
||||
"pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0"
|
||||
"pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0",
|
||||
)}
|
||||
/>
|
||||
</SwitchPrimitives.Root>
|
||||
|
|
|
|||
|
|
@ -779,7 +779,10 @@ describe("useConnection", () => {
|
|||
expect(headers).toHaveProperty("Authorization", "Bearer token123");
|
||||
expect(headers).toHaveProperty("X-Tenant-ID", "acme-inc");
|
||||
expect(headers).toHaveProperty("X-Environment", "staging");
|
||||
expect(headers).toHaveProperty("x-custom-auth-headers", JSON.stringify(["X-Tenant-ID", "X-Environment"]));
|
||||
expect(headers).toHaveProperty(
|
||||
"x-custom-auth-headers",
|
||||
JSON.stringify(["X-Tenant-ID", "X-Environment"]),
|
||||
);
|
||||
});
|
||||
|
||||
test("ignores disabled custom headers", async () => {
|
||||
|
|
@ -815,9 +818,7 @@ describe("useConnection", () => {
|
|||
headerName: "X-Custom-Auth",
|
||||
};
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useConnection(propsWithLegacyAuth),
|
||||
);
|
||||
const { result } = renderHook(() => useConnection(propsWithLegacyAuth));
|
||||
|
||||
await act(async () => {
|
||||
await result.current.connect();
|
||||
|
|
@ -825,7 +826,10 @@ describe("useConnection", () => {
|
|||
|
||||
const headers = mockSSETransport.options?.requestInit?.headers;
|
||||
expect(headers).toHaveProperty("X-Custom-Auth", "legacy-token");
|
||||
expect(headers).toHaveProperty("x-custom-auth-headers", JSON.stringify(["X-Custom-Auth"]));
|
||||
expect(headers).toHaveProperty(
|
||||
"x-custom-auth-headers",
|
||||
JSON.stringify(["X-Custom-Auth"]),
|
||||
);
|
||||
});
|
||||
|
||||
test("uses OAuth token when no custom headers or legacy auth provided", async () => {
|
||||
|
|
@ -833,9 +837,7 @@ describe("useConnection", () => {
|
|||
...defaultProps,
|
||||
};
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useConnection(propsWithoutAuth),
|
||||
);
|
||||
const { result } = renderHook(() => useConnection(propsWithoutAuth));
|
||||
|
||||
await act(async () => {
|
||||
await result.current.connect();
|
||||
|
|
@ -857,9 +859,7 @@ describe("useConnection", () => {
|
|||
headerName: "Authorization",
|
||||
};
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useConnection(propsWithBothAuth),
|
||||
);
|
||||
const { result } = renderHook(() => useConnection(propsWithBothAuth));
|
||||
|
||||
await act(async () => {
|
||||
await result.current.connect();
|
||||
|
|
|
|||
|
|
@ -17,28 +17,35 @@ export const createHeaderFromBearerToken = (
|
|||
headerName?: string,
|
||||
): CustomHeader => ({
|
||||
name: headerName || "Authorization",
|
||||
value: headerName?.toLowerCase() === "authorization" || !headerName
|
||||
? `Bearer ${bearerToken}`
|
||||
: bearerToken,
|
||||
value:
|
||||
headerName?.toLowerCase() === "authorization" || !headerName
|
||||
? `Bearer ${bearerToken}`
|
||||
: bearerToken,
|
||||
enabled: true,
|
||||
});
|
||||
|
||||
export const getEnabledHeaders = (headers: CustomHeaders): CustomHeaders => {
|
||||
return headers.filter(header => header.enabled && header.name.trim() && header.value.trim());
|
||||
return headers.filter(
|
||||
(header) => header.enabled && header.name.trim() && header.value.trim(),
|
||||
);
|
||||
};
|
||||
|
||||
export const headersToRecord = (headers: CustomHeaders): Record<string, string> => {
|
||||
export const headersToRecord = (
|
||||
headers: CustomHeaders,
|
||||
): Record<string, string> => {
|
||||
const enabledHeaders = getEnabledHeaders(headers);
|
||||
const record: Record<string, string> = {};
|
||||
|
||||
enabledHeaders.forEach(header => {
|
||||
|
||||
enabledHeaders.forEach((header) => {
|
||||
record[header.name.trim()] = header.value.trim();
|
||||
});
|
||||
|
||||
|
||||
return record;
|
||||
};
|
||||
|
||||
export const recordToHeaders = (record: Record<string, string>): CustomHeaders => {
|
||||
export const recordToHeaders = (
|
||||
record: Record<string, string>,
|
||||
): CustomHeaders => {
|
||||
return Object.entries(record).map(([name, value]) => ({
|
||||
name,
|
||||
value,
|
||||
|
|
@ -54,6 +61,6 @@ export const migrateFromLegacyAuth = (
|
|||
if (!bearerToken) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
return [createHeaderFromBearerToken(bearerToken, headerName)];
|
||||
};
|
||||
|
|
|
|||
|
|
@ -93,13 +93,17 @@ const getHttpHeaders = (req: express.Request): Record<string, string> => {
|
|||
// Handle multiple custom headers (new approach)
|
||||
if (req.headers["x-custom-auth-headers"] !== undefined) {
|
||||
try {
|
||||
const customHeaderNames = JSON.parse(req.headers["x-custom-auth-headers"] as string) as string[];
|
||||
const customHeaderNames = JSON.parse(
|
||||
req.headers["x-custom-auth-headers"] as string,
|
||||
) as string[];
|
||||
if (Array.isArray(customHeaderNames)) {
|
||||
customHeaderNames.forEach((headerName) => {
|
||||
const lowerCaseHeaderName = headerName.toLowerCase();
|
||||
if (req.headers[lowerCaseHeaderName] !== undefined) {
|
||||
const value = req.headers[lowerCaseHeaderName];
|
||||
headers[headerName] = Array.isArray(value) ? value[value.length - 1] : value;
|
||||
headers[headerName] = Array.isArray(value)
|
||||
? value[value.length - 1]
|
||||
: value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue