Package Exports
- csbridge
- csbridge/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (csbridge) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
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 ApiErrorclass 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 csbridgeConfiguration 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: "john@example.com",
    });
    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 UserLicense
MIT