import { createBasicAuthHeader } from "./config.js"; import type { AtlassianConfig, FetchLike } from "./types.js"; export type HttpMethod = "GET" | "POST" | "PUT"; export function createJsonHeaders(config: AtlassianConfig, includeJsonBody: boolean) { const headers: Array<[string, string]> = [ ["Accept", "application/json"], ["Authorization", createBasicAuthHeader(config)], ]; if (includeJsonBody) { headers.push(["Content-Type", "application/json"]); } return headers; } export async function parseResponse(response: Response) { if (response.status === 204) { return null; } const contentType = response.headers.get("content-type") ?? ""; if (contentType.includes("application/json")) { try { return await response.json(); } catch { throw new Error("Malformed JSON response from Atlassian API"); } } return response.text(); } export function createStatusError(errorPrefix: string, response: Response) { const base = `${errorPrefix}: ${response.status} ${response.statusText}`; switch (response.status) { case 401: return new Error(`${base} - check ATLASSIAN_EMAIL and ATLASSIAN_API_TOKEN`); case 403: return new Error(`${base} - verify product permissions for this account`); case 404: return new Error(`${base} - verify the resource identifier or API path`); case 429: return new Error(`${base} - retry later or reduce request rate`); default: return new Error(base); } } export async function sendJsonRequest(options: { config: AtlassianConfig; fetchImpl?: FetchLike; url: string; method: HttpMethod; body?: unknown; errorPrefix: string; handleResponseError?: (response: Response) => Error | undefined; }) { const fetchImpl = options.fetchImpl ?? globalThis.fetch; if (!fetchImpl) { throw new Error("Fetch API is not available in this runtime"); } const response = await fetchImpl(options.url, { method: options.method, headers: createJsonHeaders(options.config, options.body !== undefined), ...(options.body === undefined ? {} : { body: JSON.stringify(options.body) }), }); if (!response.ok) { const customError = options.handleResponseError?.(response); if (customError) { throw customError; } throw createStatusError(options.errorPrefix, response); } return parseResponse(response); }