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 🙏

© 2026 – Pkg Stats / Ryan Hefner

kopru

v1.0.0-beta.0

Published

Type-safe Axios-like wrapper for the Fetch API

Downloads

30

Readme

DISCLAIMER This is a work in progress project.

kopru Documentation

Kopru(Köprü in Turkish) is a modern HTTP client for JavaScript/TypeScript applications that provides a clean, promise-based API for making HTTP requests. It's designed to be feature-rich while maintaining a simple interface, similar to popular libraries like Axios.

Installation

npm install kopru
# or
yarn add kopru

Basic Usage

import kopru from "kopru";

// Simple GET request
kopru
  .get("https://api.example.com/data")
  .then((response) => {
    console.log(response.data);
  })
  .catch((error) => {
    console.error("Error:", error);
  });

// Using async/await
async function fetchData() {
  try {
    const response = await kopru.get("https://api.example.com/data");
    console.log(response.data);
  } catch (error) {
    console.error("Error:", error);
  }
}

Key Features

HTTP Methods

kopru supports all standard HTTP methods:

// GET request
kopru.get("/users");

// POST request with data
kopru.post("/users", { name: "John", email: "[email protected]" });

// PUT request
kopru.put("/users/1", { name: "John Updated" });

// PATCH request
kopru.patch("/users/1", { name: "John Patched" });

// DELETE request
kopru.delete("/users/1");

// HEAD request
kopru.head("/users");

// OPTIONS request
kopru.options("/users");

Request Configuration

You can customize requests with a configuration object:

kopru.get("/users", {
  baseURL: "https://api.example.com",
  headers: {
    Authorization: "Bearer token123",
    Accept: "application/json",
  },
  params: {
    page: 1,
    limit: 10,
    filter: "active",
  },
  timeout: 5000, // 5 seconds
  responseType: "json", // 'json', 'text', 'blob', or 'arraybuffer'
});

Creating Custom Instances

Create instances with custom default configurations:

const api = kopru.create({
  baseURL: "https://api.example.com",
  headers: {
    Authorization: "Bearer token123",
    "Content-Type": "application/json",
  },
  timeout: 10000,
});

// Now use this custom instance
api.get("/users");

Interceptors

Interceptors allow you to intercept requests or responses before they are handled:

// Request interceptor
const requestInterceptor = kopru.interceptors.request.use(
  (config) => {
    // Modify config before request is sent
    config.headers = {
      ...config.headers,
      Authorization: `Bearer ${getToken()}`,
    };
    return config;
  },
  (error) => {
    // Handle request errors
    return Promise.reject(error);
  }
);

// Response interceptor
const responseInterceptor = kopru.interceptors.response.use(
  (response) => {
    // Any status code within the range of 2xx
    return response;
  },
  (error) => {
    // Any status codes outside the range of 2xx
    if (error.status === 401) {
      // Handle unauthorized error
      refreshToken();
    }
    return Promise.reject(error);
  }
);

// Remove interceptors if needed
kopru.interceptors.request.eject(requestInterceptor);
kopru.interceptors.response.eject(responseInterceptor);

Handling Responses

Responses are structured with useful information:

kopru.get("/users/1").then((response) => {
  console.log(response.data); // Response body
  console.log(response.status); // HTTP status code
  console.log(response.statusText); // HTTP status message
  console.log(response.headers); // Response headers
  console.log(response.config); // Request configuration
});

Error Handling

Errors provide detailed information about what went wrong:

kopru.get("/users/999").catch((error) => {
  if (error.status) {
    // The request was made and the server responded with a status code
    // that falls out of the range of 2xx
    console.log(error.status);
    console.log(error.statusText);
    console.log(error.data);
    console.log(error.headers);
  } else if (error.message.includes("timeout")) {
    // The request timed out
    console.log("Request timed out");
  } else {
    // Something happened in setting up the request
    console.log("Error:", error.message);
  }
  console.log(error.config); // Request configuration
});

Timeout Handling

Set timeouts to abort requests that take too long:

// Set a 5-second timeout
kopru.get("/users", { timeout: 5000 }).catch((error) => {
  if (error.message.includes("timeout")) {
    console.log("Request timed out after 5 seconds");
  }
});

Abort Requests

Cancel requests using AbortController:

const controller = new AbortController();

kopru.get("/users", { signal: controller.signal }).catch((error) => {
  if (error.name === "AbortError") {
    console.log("Request was cancelled");
  }
});

// Cancel the request
controller.abort();

Different Response Types

Handle various response formats:

// Get JSON (default)
kopru.get("/data", { responseType: "json" });

// Get text
kopru.get("/data.txt", { responseType: "text" });

// Get binary data
kopru.get("/image.png", { responseType: "blob" });

// Get ArrayBuffer
kopru.get("/data.bin", { responseType: "arraybuffer" });

Advanced Example

// Create a custom instance
const api = kopru.create({
  baseURL: "https://api.example.com/v1",
  timeout: 8000,
  headers: {
    "Content-Type": "application/json",
    Accept: "application/json",
  },
});

// Add request interceptor to add auth token
api.interceptors.request.use((config) => {
  const token = localStorage.getItem("token");
  if (token) {
    config.headers = {
      ...config.headers,
      Authorization: `Bearer ${token}`,
    };
  }
  return config;
});

// Add response interceptor for error handling
api.interceptors.response.use(
  (response) => response,
  async (error) => {
    // Handle token refresh on 401 errors
    if (error.status === 401 && !error.config._retry) {
      error.config._retry = true;
      try {
        const refreshToken = localStorage.getItem("refreshToken");
        const response = await api.post("/auth/refresh", { token: refreshToken });
        const newToken = response.data.token;
        localStorage.setItem("token", newToken);

        // Retry the original request with new token
        error.config.headers["Authorization"] = `Bearer ${newToken}`;
        return api.request(error.config);
      } catch (refreshError) {
        // Refresh token failed, redirect to login
        window.location.href = "/login";
        return Promise.reject(refreshError);
      }
    }
    return Promise.reject(error);
  }
);

// Export for use throughout the application
export default api;