npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

fetchfully

v1.6.0

Published

JavaScript Fetch API with power pack ⚡️

Readme

Fetchfully

Fetchfully wraps the JavaScript Fetch API with additional functionalities for simplicity and efficiency. It's the Javascript Fetch API with Power Pack ⚡️


Features

  • Object-first data fetching: Supply all init config as object, improving code clarity.
  • In-built request Logic: Automatically handles responses based on content type.
  • Parses JSON payload: Parses mutation request payload as JSON.
  • Simple path and query parameters: Work better with URL parameters. Pass path and query parameter as object value. Tweak query parameters delimiter in config.
  • Global config and instances: Create different instances that use a global config or override it with instance-specific config.
  • Consumable request method: Use consumable methods for ergonomic common HTTP requests.
  • Request status: Monitor request status for loading, failed and successful network request states.
  • Refetch request: Easily make refetch without reconstructing request config.
  • Fully Type: Use Typescript and exports all necessary types for easy configuration

Installation

Install the package using npm or yarn:

npm install fetchfully

How To Use

Basic request with default instance

NOTE: The API endpoints below are for demonstration purposes only. Test on live endpoints for expected result.

1. Normal request
import fetcher from "fetchfully";

await fetcher({ url: "https://api.example.com/posts" });
2. With path string
await fetcher({
  url: "https://api.example.com",
  path: "posts1/comments",
});

// URL results in: https://api.example.com/posts/1/commments
3. With array of path segments
await fetcher({
  url: "https://api.example.com",
  path: ["posts", "1", "comments"],
});

// URL results in: https://api.example.com/posts/1/commments
4. With query parameters
const query = {
  page: 1,
  limit: 10,
  colors: ["red", "blue"],
  size: "large",
};

await fetcher({
  url: "https://api.example.com",
  query,
  queryArrayFormat = "comma",
});

// URL results in: https://api.example.com/comments?page=1&limit=10&colors=red,blue&size=large

Mutation request (POST, PUT, PATCH and DELETE)

1. POST request
await fetcher({
  url: "https://api.example.com/post",
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: {
    title: "foo",
    body: "bar",
    userId: 1,
  },
});
2. PUT request
await fetcher({
  url: "https://api.example.com/post",
  method: "PUT",
  headers: {
    Authorization: "Bearer token",
    "Content-Type": "application/json",
  },
  body: {
    id: 1,
    title: "foo",
    body: "bar",
    userId: 1,
  },
});
3. PATCH request
await fetcher({
  url: "https://api.example.com/post/1",
  method: "PATCH",
  headers: {
    "Content-Type": "application/json",
  },
  body: { title: "bar" },
});
4. Delete request
await fetcher({ url: "https://api.example.com/post/1", method: "DELETE" });

Fetchfully Configuration

When initializing Fetchfully, you can pass the following options:

Base options

| Option | Type | Description | | ------------------ | --------------------------------------------- | -------------------------------------------------- | | baseUrl | String | Base URL for all requests. | | path | string \| string[] \| undefined | URL path segments. | | query | string \| string[] \| undefined | URL query parameters. | | method | string | Request action method. | | body | string \| undefined | Request payload. | | credentials | "same-origin" \| "omit" \| "include" | Request credentials. | | keepalive | boolean | Persist requests request connection. | | mode | "same-origin" \| "cors" \| "no-cors" | Request CORS mode. | | timeout | number | Time as milliseconds before terminating request. | | queryArrayFormat | "brackets" \| "comma" \| "repeat" \| "none" | Indicates how parameter array should be formatted. |

Fetchfully Instance

Create new instance of Fetchfully with independent custom configurations with the fetcher.create() factory method.

import fetcher from "fetchfully";

// api/auth
const authAPI = fetchfully.create({
  baseUrl: "https://api.example.com/auth",
  timeout: 5000,
});

// api/users
const userAPI = fetcher.create({
  baseURL: "https://api.example.com/user",
  headers: {
    "Cache-Control": "no-cache",
  },
});

// api/analytics
const analyticsAPI = fetcher.create({
  baseURL: "https://api.example.com/analytics",
  timeout: 5000,
});

Fetchfully Default Config

Create a global config that will persist across all requests

Global default
import fetcher from "fetchfully";

fetcher.defaults.baseUrl = "https://api.example.com";
fetcher.defaults.timeout = 5000;
Custom default by instance
const customAPI = fetcher.create({
  headers: {
    Authorization: "Bearer token", // Instance specific authorization header
  },
  timeout: 2500, // Instance specific timeout.
});

// Use custom instance
await customAPI({
  path: "users",
  query: { active: true }, // 'https://api.example.com/users?active=true
});

Instance specific configs take precedence over those in global default config. For instance, the 2500 (2.5 seconds) set above is specific to that instance alone.

Consumable methods for ergonomic requests.

Use these ergonomic methods for common HTTP request.

Set base URL
import fetcher from "fetchfully";

fetcher.defaults.baseUrl = "https://api.example.com";
GET request
// Using convenience methods
await fetcher.get("users");
await fetcher.get("users", { active: true }); // https://api.example.com/users?active=true
POST request
await fetcher.post("users", {
  name: "John",
  email: "[email protected]",
});
PUT request
await fetcher.put("users/123", {
  name: "John Doe",
});
PATCH request
await fetcher.patch("users/123", {
  status: "active",
});
PATCH request
await fetcher.delete("users/123");

Fetchfully Refetch

The refetch method lets you re-run the exact same request with the same configuration to get fresh data without reconstructing entire request.

// Example 1: Basic refetch
const response = await fetchfully.get("/api/users");

if (response.isSuccess) {
  console.log("Users:", response.data);

  const freshResponse = await response.refetch?.();
  console.log("Updated users:", freshResponse.data);
}

// Example 2: Refetch on user action
const userResponse = await fetchfully.get("/api/user/123");

const handleRefresh = async () => {
  if (userResponse.refetch) {
    const refreshed = await userResponse.refetch();
    if (refreshed.isSuccess) {
      setUser(refreshed.data); // Update UI with fresh data
    }
  }
};

License

This project is licensed under the MIT.