Not an another HTTP client but a fetch wrapper with fluent API and superpowers
fetchp is "not an another HTTP client but a fetch wrapper with fluent API and superpowers". The trailing "p" is a means for "plus".
fetch is a standard Web API that's already supported by modern browsers, Deno, node.js, bun and etc.
We don't need another HTTP client. Still, a web API's target audience is very broad. APIs like fetch are being designed carefully by the community and organizations to be used by the general public. Any design mistake can cause lots of unrecoverable problems. For this reason, they're keeping it simple and running away from the idea of increasing the extra features they can cover.
So, if you want to use fetch, you may need to wrap it with some extra functionality from time to time. For example, if you call it from a React web project, checking its loading state almost is a must. Or, if you're writing automated tests for your application, you need to mock the fetch API.
This is where fetchp comes into play. It still uses fetch's native implementation that brought you by browsers or runtimes themselves, but in the meantime, it wraps the fetch to provide extra functionality for developers.
Fetchp tries to assemble some tools that are useful and reusable for most of the projects that fetch doesn't provide.
Moreover, since fetchp is a JavaScript module / npm package, it also follows the semantic versioning and its API can be evolved in the future without breaking any project.
More to come see Todo List section.
Execute npm install fetchp
or yarn add fetchp
to install fetchp and its
dependencies into your project directory.
import { fetchp } from "fetchp";
// you don't need to await request
const req = fetchp.request("GET", "https://www.google.com/");
// you may await data instead...
// once your request is completed, it will return a string
console.log(await req.data);
import { fetchp } from "fetchp";
const req = fetchp.request("GET", "https://jsonplaceholder.typicode.com/posts");
// since your request will return a json, req.data will return an object
console.log(await req.data);
import { fetchp, FetchpStatus } from "fetchp";
const doReq = () =>
fetchp.request(
"GET",
"https://jsonplaceholder.typicode.com/posts",
{ cacheRequest: true },
);
const response1 = doReq();
await new Promise((r) => setTimeout(r, 1000));
const response2 = doReq();
// you can check equality afterwars
assert(await response1.data === await response2.data);
import { fetchp, FetchpStatus } from "fetchp";
const req = fetchp.request("GET", "https://jsonplaceholder.typicode.com/posts");
// abort it after 500 milliseconds
setTimeout(() => req.abortController.abort(), 500);
// you can check status afterwars
assert(req.status === FetchpStatus.CANCELED);
Assume that you're working with a single API on the backend, and you don't want to repeat yourself by concatenating endpoint URL strings in each request you make.
import { fetchp } from "fetchp";
fetchp.setBaseUri("https://jsonplaceholder.typicode.com");
const req = fetchp.request("GET", "/posts");
console.log(await req.data);
Assume that you're need to add additional headers to each request you make.
import { fetchp, FetchpHookType } from "fetchp";
fetchp.hooks.add(
FetchpHookType.BuildRequestHeaders,
(headers) => headers.set("Authorization", `Bearer ${getIdToken()}`);
);
const response = fetchp.request(
"GET",
"https://localhost/api/some-restricted-endpoint"",
);
Assume that you're need to observe state changes only for the urls in your filter.
import { fetchp, FetchpHookType } from "fetchp";
fetchp.hooks.addForUrl(
FetchpHookType.StateChange,
["GET", "POST"],
/^https:\/\/jsonplaceholder\.typicode\.com\//,
(request, status) =>
console.log(`[state change] ${request.url} -> ${status}`),
);
const response = fetchp.request(
"GET",
"https://jsonplaceholder.typicode.com/todos",
);
Assume that you don't want to invoke the request immediately. You'll set up an external trigger for this.
import { fetchp } from "fetchp";
const req = fetchp.request("GET", "/posts", { immediate: false });
setTimeout(() => req.exec(), 500);
console.log(await req.data);
Assume that your API is not yet built on the backend, and you want to mock its behavior.
import { fetchp } from "fetchp";
const mockContent = { hello: "world" };
const mockResponse = (request) =>
new Response(
JSON.stringify(mockContent),
{
status: 200,
statusText: "OK",
headers: {
"content-type": "application/json",
},
},
);
fetchp.mocks.add(["GET", "POST"], "/hello", mockResponse);
// mocking is done, let's make a request to the mocked URL
const req = fetchp.request("GET", "/hello");
// it will return { hello: "world" }
console.log(await req.data);
Assume that you want to mock your code without dealing with a test framework and
its interfaces / methods. All you need to do is importing fetchp/mock
instead
of fetchp
module.
// just replace fetchp with fetchp/mock
import { fetchp } from "fetchp/mock";
const req = fetchp.request("GET", "/posts");
console.log(await req.data);
import { useFetchp } from "fetchp";
const MyComponent = (props) => {
const { data, isLoading, error } = useFetchp("GET", "/posts");
if (isLoading) {
return <div>Loading...</div>;
}
if (error) {
return <div>Error: {error.message}</div>;
}
return <div>{JSON.stringify(data)}</div>;
};
// just replace fetchp with fetchp/mock
import { useFetchp } from "fetchp/mock";
const MyComponent = (props) => {
const { data, isLoading, error } = useFetchp("GET", "/posts");
if (isLoading) {
return <div>Loading...</div>;
}
if (error) {
return <div>Error: {error.message}</div>;
}
return <div>{JSON.stringify(data)}</div>;
};
import { useEffect } from "react";
import { useFetchp } from "fetchp";
const MyComponent = (props) => {
const { data, status, isSuccess, doFetch } = useFetchp(
"GET",
"/posts",
false,
);
useEffect(() => {
// fetch data after 500 milliseconds have passed
setTimeout(() => doFetch(), 500);
}, []);
if (!isSuccess) {
return <div>Status: {status}...</div>;
}
return <div>{status}: {JSON.stringify(data)}</div>;
};
import { fetchp } from "npm:fetchp";
const req = fetchp.request("GET", "https://www.google.com/");
console.log(await req.data);
See GitHub Projects for more.
fetchp/mock
moduleApache 2.0, for further details, please see LICENSE file
See contributors.md
It is publicly open for any contribution. Bugfixes, new features and extra modules are welcome.
Visit my GitHub Sponsors profile at github.com/sponsors/eserozvataf