[](https://www.npmjs.com/package/@marianmeres/http-utils) [](https://jsr.io/@marianmeres/http-utils) [


Opinionated, lightweight HTTP client wrapper for fetch with type-safe errors and convenient defaults.
- đ¯ Type-safe HTTP errors - Well-known status codes map to specific error classes
- đ§ Convenient defaults - Auto JSON parsing, Bearer tokens, base URLs
- đĒļ Lightweight - Zero dependencies, thin wrapper over native fetch
- đ¨ Flexible error handling - Three-tier error message extraction (local â factory â global)
- đĻ Deno & Node.js - Works in both runtimes
- đĻž Generic return types - Optional type parameters for typed responses
``shell`
deno add jsr:@marianmeres/http-utils
`shell`
npm install @marianmeres/http-utils
`ts`
import { createHttpApi, opts, HTTP_ERROR } from "@marianmeres/http-utils";
`ts
import { createHttpApi, opts, HTTP_ERROR, NotFound } from "@marianmeres/http-utils";
// Create an API client with base URL
const api = createHttpApi("https://api.example.com", {
headers: { "Authorization": "Bearer your-token" }
});
// GET request (options API with opts() wrapper)
const users = await api.get("/users", opts({
params: { headers: { "X-Custom": "value" } }
}));
// POST request (options API with opts() wrapper)
const newUser = await api.post("/users", opts({
data: { name: "John Doe" },
params: { headers: { "X-Custom": "value" } }
}));
// Legacy API (default behavior without opts())
const legacyUsers = await api.get("/users", { headers: { "X-Custom": "value" } });
const legacyUser = await api.post("/users", { name: "John Doe" });
// With type parameters for typed responses
interface User { id: number; name: string; }
const user = await api.get
const created = await api.post
// Error handling
try {
await api.get("/not-found");
} catch (error) {
if (error instanceof NotFound) {
console.log("Resource not found");
}
// or use the namespace
if (error instanceof HTTP_ERROR.NotFound) {
console.log(error.status); // 404
console.log(error.body); // Response body
}
}
`
Creates an HTTP API client.
`ts`
const api = createHttpApi("https://api.example.com", {
headers: { "Authorization": "Bearer token" }
});
`ts
// GET (options API with opts() wrapper)
const data = await api.get("/users", opts({
params: { headers: { "X-Custom": "value" } },
respHeaders: {}
}));
// POST/PUT/PATCH/DELETE (options API with opts() wrapper)
await api.post("/users", opts({
data: { name: "John" },
params: { token: "bearer-token" }
}));
// Legacy API (default behavior without opts())
const data = await api.get("/users", { headers: { "X-Custom": "value" } });
await api.post("/users", { name: "John" });
`
The opts() function explicitly marks an options object for the options-based API. Without it, arguments are treated as legacy positional parameters.
`ts
// Without opts() - legacy behavior: object is sent as request body
await api.post("/users", { data: { name: "John" } }); // Sends: { data: { name: "John" } }
// With opts() - options API: data is extracted and sent as body
await api.post("/users", opts({ data: { name: "John" } })); // Sends: { name: "John" }
`
This makes the API unambiguous and prevents accidental misinterpretation of request data.
`ts
import { HTTP_ERROR, NotFound } from "@marianmeres/http-utils";
try {
await api.get("/resource");
} catch (error) {
if (error instanceof NotFound) {
console.log("Not found:", error.body);
}
// All errors have: status, statusText, body, cause
}
`
- Auto JSON: Response bodies are automatically parsed as JSON
- Bearer tokens: Use token param to auto-add Authorization: Bearer headerrespHeaders: {}
- Response headers: Pass to capture response headersraw: true
- Raw response: Use to get the raw Response objectassert: false
- Non-throwing: Use to prevent throwing on errorssignal
- AbortController: Pass for request cancellationapi.get
- Typed responses: Use generics for type-safe responses:
For complete API documentation including all error classes, HTTP status codes, types, and utilities, see API.md.
Extracts human-readable messages from any error format:
`ts
import { getErrorMessage } from "@marianmeres/http-utils";
try {
await api.get("/fail");
} catch (error) {
console.log(getErrorMessage(error)); // "Not Found"
}
`
Manually create HTTP errors:
`ts
import { createHttpError } from "@marianmeres/http-utils";
const error = createHttpError(404, "User not found", { userId: 123 });
throw error; // instanceof NotFound
``