ApiService is a class that provides a simple and consistent interface for making HTTP requests to REST APIs. It supports all common HTTP methods (GET, POST, PUT, PATCH, DELETE), automatic header management, token-based authentication, and optional debug logging.ts
import { ApiService } from "@arkyn/server/apiService";
baseUrl (required): The base URL for all API requests. This will be prepended to all endpoint paths.baseHeaders (optional): Default headers to include in every request. These can be overridden by request-specific headers.baseToken (optional): A default Bearer token for authorization. This can be overridden by request-specific tokens.enableDebug (optional): Enable debug logging for requests. When true, request details will be logged using flushDebugLogs. Default is false.timeoutMs (optional): Default request timeout, in milliseconds, for every request made by this instance. Added in v3.0.12. Can be overridden per request, see timeoutMs under "Request data options" below. Falls back to 10000 (10s) if not set here or per request.typescript
const api = new ApiService({baseUrl: "https://api.example.com",baseHeaders: { "Content-Type": "application/json" },baseToken: "your-api-token",enableDebug: true,timeoutMs: 15000,});
success: A boolean indicating whether the request was successful.status: The HTTP status code of the response.message: A message describing the result of the request.response: The parsed response payload (generic type T).cause: Additional error information, if applicable (string | Error | null).get(endpoint, data?) - Sends a GET request to the specified endpoint.post(endpoint, data?) - Sends a POST request with an optional body.put(endpoint, data?) - Sends a PUT request with an optional body.patch(endpoint, data?) - Sends a PATCH request with an optional body.delete(endpoint, data?) - Sends a DELETE request with an optional body.headers: Additional headers for this requesttoken: Bearer token (overrides baseToken)urlParams: Values substituted into :paramName placeholders in the endpoint path (not appended as a query string)timeoutMs (optional, added in v3.0.12): Per-request timeout in milliseconds, overrides the instance's timeoutMs for this call only. Defaults to 10000 (10s) if neither this nor the instance default is set.body: Request body (any serializable data)headers: Additional headers for this requesttoken: Bearer token (overrides baseToken)urlParams: Values substituted into :paramName placeholders in the endpoint path (not appended as a query string)timeoutMs (optional, added in v3.0.12): Per-request timeout in milliseconds, overrides the instance's timeoutMs for this call only. Defaults to 10000 (10s) if neither this nor the instance default is set.typescript
import { ApiService } from "@arkyn/server/apiService";const api = new ApiService({baseUrl: "https://api.example.com",baseHeaders: { "Content-Type": "application/json" },enableDebug: process.env.NODE_ENV === "development",});// GET request with a route variableconst user = await api.get("/users/:id", {urlParams: { id: "42" },});// GET request with custom tokenconst profile = await api.get("/me", {token: "user-specific-token",});// POST request with bodyconst newUser = await api.post("/users", {body: { name: "John", email: "john@example.com" },});// PUT requestconst updatedUser = await api.put("/users/:userId", {body: { name: "John Doe" },urlParams: { userId: "123" },});// PATCH requestconst patchedUser = await api.patch("/users/:userId", {body: { status: "active" },urlParams: { userId: "123" },});// DELETE requestconst deleted = await api.delete("/users/:userId", {urlParams: { userId: "123" },});// Handling responsesif (user.status === 200) {console.log(user.response); // Response data} else {console.log(user.message); // Error message}
baseToken (as Authorization: Bearer {token})baseHeaders (from constructor)headers (from request data)token (from request data, as Authorization: Bearer {token})Content-Type is always forced to application/json by the client after the headers above are merged, so it cannot be overridden via baseHeaders or per-request headers.enableDebug is enabled, each request logs the following information:flushDebugLogs with the "yellow" color scheme.parseSensitiveData before being logged, so Authorization and other sensitive fields (Cookie, password, token, apiKey, secret, matched case-insensitively) print as "****" instead of their real value. Non-sensitive data is unaffected.AbortController if it doesn't complete within timeoutMs (per-request value, falling back to the instance's timeoutMs, falling back to 10000, 10s). Previously, requests had no timeout at all and could hang indefinitely on a stalled connection.typescript
const result = await api.get("/slow-endpoint", { timeoutMs: 2000 });if (!result.success && result.status === 504) {console.log(result.message); // "Request timed out after 2000ms"}
success: false and the generic "Network error or request failed" message, with no fixed status override./users/:userId becomes /users/123):param syntax is optional, but recommended when integrating with LogService. The log system generates logs based on URLs, so having a consistent base URL with variables as route parameters makes logs more readable and aggregatable.typescript
// Without route variables - each userId creates a different log entryawait api.get("/users/123");await api.get("/users/456");// Logs: GET /users/123, GET /users/456// With route variables - logs are grouped by the base patternawait api.get("/users/:userId", { urlParams: { userId: "123" } });await api.get("/users/:userId", { urlParams: { userId: "456" } });// Logs: GET /users/:userId (with userId as metadata)
baseUrl to all endpoint paths, so endpoints should start with /.success, status, message, response, and cause properties.