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

csbridge

v1.0.11

Published

A TypeScript utility library for handling API requests with robust error handling

Readme

CSBridge - Simple API Service

Overview

CSBridge is a lightweight TypeScript API service for handling HTTP requests with built-in error handling, retry logic, and timeout support. It provides a simple interface for making API calls with proper TypeScript support and flexible configuration options.

Features

  • Type-Safe API: Fully typed API service with TypeScript support
  • Custom Error Handling: Built-in ApiError class with detailed error information
  • HTTP Methods: Support for GET, POST, PUT, PATCH, DELETE operations
  • File Operations: Upload and download file support
  • Retry Logic: Configurable retry with exponential backoff
  • Timeout Handling: Built-in request timeout with abort controller
  • Flexible Configuration: Global config, per-request options, or no config
  • Authentication Support: Easy header management for authentication

Installation

npm install csbridge

Configuration Options

CSBridge offers three ways to configure your API requests:

1. Global Configuration (API_CONFIG)

2. Per-Request Configuration

3. No Configuration (Minimal Setup)


1. Using Global Configuration (API_CONFIG)

Set up global configuration that applies to all requests:

import apiService, { API_CONFIG, ApiError } from "csbridge";

// Configure global settings
API_CONFIG.baseUrl = "https://api.example.com";
API_CONFIG.timeout = 60000; // 60 seconds
API_CONFIG.retryCount = 3;
API_CONFIG.retryDelay = 500; // 500ms
API_CONFIG.retriableStatuses = [408, 429, 500, 502, 503, 504];
API_CONFIG.defaultHeaders = {
  Authorization: "Bearer your-token",
  "Content-Type": "application/json",
  "X-API-Key": "your-api-key",
};

// Now all requests use these global settings
async function globalConfigExample() {
  try {
    // GET request - uses global config
    const users = await apiService.get("/users");
    console.log("Users:", users.data);

    // POST request - uses global config
    const newUser = await apiService.post("/users", {
      name: "John Doe",
      email: "[email protected]",
    });
    console.log("Created user:", newUser.data);

    // File upload - uses global config
    const file = new File(["content"], "test.txt", { type: "text/plain" });
    const uploadResult = await apiService.upload("/files", file);
    console.log("Upload successful:", uploadResult.data);
  } catch (error) {
    if (error instanceof ApiError) {
      console.error(`API Error ${error.status}: ${error.message}`);
    }
  }
}

2. Per-Request Configuration

Override global settings or configure individual requests:

import apiService, { ApiError } from "csbridge";

async function perRequestConfigExample() {
  try {
    // Example 1: Custom headers for specific request
    const response1 = await apiService.get("/protected-data", {
      headers: {
        Authorization: "Bearer different-token",
        "X-Custom-Header": "custom-value",
      },
    });

    // Example 2: Custom timeout for slow endpoint
    const response2 = await apiService.get("/slow-endpoint", {
      timeout: 120000, // 2 minutes for this request
      headers: {
        Accept: "application/json",
      },
    });

    // Example 3: Custom retry configuration
    const response3 = await apiService.post(
      "/unreliable-service",
      {
        data: "important-data",
      },
      {
        retry: true,
        retryOptions: {
          retries: 5,
          delay: 1000,
          retriableStatuses: [408, 429, 500, 502, 503, 504],
        },
        timeout: 30000,
      }
    );

    // Example 4: Disable retry for specific request
    const response4 = await apiService.get("/fast-endpoint", {
      retry: false, // No retries for this request
      timeout: 5000,
    });

    // Example 5: Custom retry for rate-limited endpoint
    const response5 = await apiService.post(
      "/rate-limited-api",
      { data: "test" },
      {
        retryOptions: {
          retries: 3,
          delay: 2000,
          retriableStatuses: [429], // Only retry on rate limit
        },
      }
    );

    console.log("All requests completed successfully");
  } catch (error) {
    if (error instanceof ApiError) {
      console.error("Request failed:", {
        status: error.status,
        message: error.message,
        timestamp: error.timestamp,
      });
    }
  }
}

3. Minimal Setup (No Configuration)

Use the API service without any configuration for simple use cases:

import apiService, { ApiError } from "csbridge";

async function minimalExample() {
  try {
    // Simple GET request with full URL
    const response1 = await apiService.get("https://jsonplaceholder.typicode.com/users");
    console.log("Users:", response1.data);

    // Simple POST request
    const response2 = await apiService.post("https://jsonplaceholder.typicode.com/posts", {
      title: "My Post",
      body: "Post content",
      userId: 1,
    });
    console.log("Created post:", response2.data);

    // Simple PUT request
    const response3 = await apiService.put("https://jsonplaceholder.typicode.com/posts/1", {
      id: 1,
      title: "Updated Post",
      body: "Updated content",
      userId: 1,
    });
    console.log("Updated post:", response3.data);

    // Simple DELETE request
    await apiService.delete("https://jsonplaceholder.typicode.com/posts/1");
    console.log("Post deleted");
  } catch (error) {
    if (error instanceof ApiError) {
      console.error(`Error ${error.status}: ${error.message}`);
    }
  }
}

API Methods

HTTP Methods

  • get<T>(url, options?) - GET request
  • post<T, D>(url, data?, options?) - POST request
  • put<T, D>(url, data?, options?) - PUT request
  • patch<T, D>(url, data?, options?) - PATCH request
  • delete<T>(url, options?) - DELETE request
  • upload<T>(url, file, options?) - File upload
  • download(url, options?) - File download

Configuration Methods

  • setBaseUrl(url) - Set the base URL for all requests
  • setDefaultHeaders(headers) - Set default headers for all requests

Configuration Reference

API_CONFIG Properties

interface ApiConfig {
  baseUrl: string; // Base URL for all requests
  timeout: number; // Request timeout in milliseconds
  defaultHeaders: Record<string, string>; // Default headers for all requests
  retryCount: number; // Number of retry attempts
  retryDelay: number; // Base delay between retries (ms)
  retriableStatuses: number[]; // HTTP status codes to retry on
}

Request Options

interface RequestOptions {
  headers?: Record<string, string>; // Custom headers for this request
  timeout?: number; // Custom timeout for this request
  retry?: boolean; // Enable/disable retry for this request
  retryOptions?: {
    // Custom retry configuration
    retries: number; // Number of retry attempts
    delay: number; // Base delay between retries
    retriableStatuses: number[]; // Status codes to retry on
  };
}

Mixed Configuration Examples

You can combine different configuration approaches:

import apiService, { API_CONFIG, ApiError } from "csbridge";

// Set some global defaults
API_CONFIG.baseUrl = "https://api.example.com";
API_CONFIG.timeout = 30000;
API_CONFIG.defaultHeaders = {
  Authorization: "Bearer global-token",
};

async function mixedConfigExample() {
  try {
    // Use global config
    const users = await apiService.get("/users");

    // Override specific settings
    const reports = await apiService.get("/reports", {
      timeout: 60000, // Override timeout
      headers: {
        Authorization: "Bearer admin-token", // Override auth
      },
    });

    // Use full URL (ignores baseUrl)
    const external = await apiService.get("https://external-api.com/data");

    // Custom retry for critical operation
    const important = await apiService.post("/critical-data", data, {
      retryOptions: {
        retries: 5,
        delay: 2000,
      },
    });
  } catch (error) {
    console.error("Request failed:", error);
  }
}

Error Handling

ApiError Class

The ApiError class provides structured error information:

class ApiError extends Error {
  status: number; // HTTP status code
  code: string; // Error code (e.g., "HTTP_404")
  data: unknown; // Additional error data from response
  timestamp: Date; // When the error occurred
}

Error Handling Examples

try {
  const response = await apiService.get("/users");
  return response.data;
} catch (error) {
  if (error instanceof ApiError) {
    switch (error.status) {
      case 401:
        console.log("Authentication required");
        // Redirect to login
        break;
      case 403:
        console.log("Access forbidden");
        break;
      case 404:
        console.log("Resource not found");
        break;
      case 429:
        console.log("Rate limited - too many requests");
        break;
      case 500:
        console.log("Server error");
        break;
      default:
        console.log(`API Error: ${error.message}`);
    }
  } else {
    console.error("Unexpected error:", error);
  }
}

Complete Working Example

import apiService, { API_CONFIG, ApiError } from "csbridge";

// Configure for your API
API_CONFIG.baseUrl = "https://jsonplaceholder.typicode.com";
API_CONFIG.timeout = 30000;
API_CONFIG.retryCount = 3;
API_CONFIG.retryDelay = 500;

interface User {
  id: number;
  name: string;
  email: string;
}

interface Post {
  id: number;
  title: string;
  body: string;
  userId: number;
}

async function completeExample() {
  try {
    console.log("=== CSBridge API Service Example ===");

    // 1. GET request with global config
    console.log("\n1. Fetching users...");
    const usersResponse = await apiService.get<User[]>("/users");
    console.log(`Found ${usersResponse.data.length} users`);

    // 2. POST request with custom retry
    console.log("\n2. Creating post with custom retry...");
    const newPost = await apiService.post<Post>(
      "/posts",
      {
        title: "My Test Post",
        body: "This is a test post created with CSBridge",
        userId: 1,
      },
      {
        retryOptions: {
          retries: 2,
          delay: 1000,
        },
      }
    );
    console.log("Created post:", newPost.data);

    // 3. GET with custom timeout
    console.log("\n3. Fetching specific user with custom timeout...");
    const userResponse = await apiService.get<User>("/users/1", {
      timeout: 10000, // 10 seconds
    });
    console.log("User details:", userResponse.data);

    // 4. PUT request with no retry
    console.log("\n4. Updating post without retry...");
    const updatedPost = await apiService.put<Post>(
      `/posts/${newPost.data.id}`,
      {
        id: newPost.data.id,
        title: "Updated Title",
        body: "Updated content",
        userId: 1,
      },
      {
        retry: false,
      }
    );
    console.log("Updated post:", updatedPost.data);

    // 5. DELETE request
    console.log("\n5. Deleting post...");
    await apiService.delete(`/posts/${newPost.data.id}`);
    console.log("Post deleted successfully");

    console.log("\n✅ All operations completed successfully!");
  } catch (error) {
    if (error instanceof ApiError) {
      console.error("❌ API Error:", {
        status: error.status,
        message: error.message,
        code: error.code,
        timestamp: error.timestamp,
      });
    } else {
      console.error("❌ Unexpected error:", error);
    }
  }
}

// Run the example
completeExample();

TypeScript Support

CSBridge provides full TypeScript support with generic types:

// Response typing
const response = await apiService.get<User[]>("/users");
// response.data is typed as User[]

// Request/response typing
const createUser = await apiService.post<User, CreateUserRequest>("/users", userData);
// userData must match CreateUserRequest type
// response.data is typed as User

License

MIT