My implementation of httpService in my TS projects,

'use server';
 
import { getLogger } from "@/lib/logger";
import {none, Option, some} from "fp-ts/Option";
 
const DEFAULT_TIMEOUT = 30000; // 30 seconds
 
export const httpPost = async <RequestType, ResponseType>(
  url: string, 
  requestBody: RequestType,
  timeoutMs: number = DEFAULT_TIMEOUT
): Promise<Option<ResponseType>> => {
  const logger = getLogger()
  try {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
 
    const response = await fetch(
      url,
      {
        method: 'POST',
        headers: {
          "Content-Type": "application/json"
        },
        body: JSON.stringify(requestBody),
        signal: controller.signal
      }
    )
 
    clearTimeout(timeoutId);
 
    if (!response.ok) {
      logger.error(`httpPost error, returned ${response.status}`, url, requestBody)
      return none;
    }
    const responseJson: ResponseType = await response.json()
    return some(responseJson)
  } catch (error) {
    if (error instanceof Error) {
      if (error.name === 'AbortError') {
        logger.error(`httpPost timeout after ${timeoutMs}ms`, url);
      } else {
        logger.error("httpPost failed", error);
      }
    }
    return none;
  }
}