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

@uecsio/api-client

v1.0.1

Published

A reusable TypeScript API client wrapper for HTTP requests with flexible authentication

Readme

@uecsio/api-client

A reusable TypeScript API client wrapper for making HTTP requests with built-in authentication handling and error management.

Installation

npm install @uecsio/api-client

Features

  • 🔒 Built-in authentication token management
  • 🔄 Automatic 401 unauthorized handling
  • 📦 TypeScript support with full type definitions
  • 🎯 RESTful API methods (GET, POST, PUT, PATCH, DELETE)
  • ⚙️ Configurable base URL and headers
  • 🔌 Extensible with custom callbacks
  • 🛠️ Access to underlying Axios instance for advanced use cases

Quick Start

import { ApiClient } from '@uecsio/api-client';

// Create an API client instance
const apiClient = new ApiClient({
  baseUrl: 'https://api.example.com',
});

// Make requests
const users = await apiClient.get('/users');
const newUser = await apiClient.post('/users', { name: 'John Doe' });

Configuration

Basic Configuration

const apiClient = new ApiClient({
  baseUrl: 'https://api.example.com',
  token: 'your-auth-token', // Optional initial token
  headers: { // Optional custom headers
    'X-Custom-Header': 'value',
  },
});

With Authentication Callbacks

For browser environments with localStorage:

const apiClient = new ApiClient({
  baseUrl: process.env.REACT_APP_API_URL,
  
  // Get token from localStorage
  getToken: () => localStorage.getItem('token'),
  
  // Save token to localStorage
  saveToken: (token) => localStorage.setItem('token', token),
  
  // Clear token from localStorage
  clearToken: () => localStorage.removeItem('token'),
  
  // Handle unauthorized responses (e.g., redirect to login)
  onUnauthorized: () => {
    window.location.href = '/login';
  },
});

For Node.js or other environments:

let authToken: string | null = null;

const apiClient = new ApiClient({
  baseUrl: 'https://api.example.com',
  getToken: () => authToken,
  saveToken: (token) => { authToken = token; },
  clearToken: () => { authToken = null; },
  onUnauthorized: () => {
    console.log('Session expired, please login again');
  },
});

API Methods

GET Request

// Simple GET
const users = await apiClient.get('/users');

// With query parameters
const users = await apiClient.get('/users', {
  params: { page: 1, limit: 10 },
});

// With custom headers
const users = await apiClient.get('/users', {
  headers: { 'X-Custom-Header': 'value' },
});

// With TypeScript types
interface User {
  id: number;
  name: string;
}
const users = await apiClient.get<User[]>('/users');

POST Request

const newUser = await apiClient.post('/users', {
  name: 'John Doe',
  email: '[email protected]',
});

// With TypeScript types
interface CreateUserResponse {
  id: number;
  name: string;
  email: string;
}
const user = await apiClient.post<CreateUserResponse>('/users', {
  name: 'John Doe',
  email: '[email protected]',
});

PUT Request

const updatedUser = await apiClient.put('/users/123', {
  name: 'Jane Doe',
  email: '[email protected]',
});

PATCH Request

const updatedUser = await apiClient.patch('/users/123', {
  name: 'Jane Doe',
});

DELETE Request

await apiClient.delete('/users/123');

File Upload

const formData = new FormData();
formData.append('file', fileInput.files[0]);
formData.append('description', 'Profile picture');

const result = await apiClient.upload('/upload', formData);

// With additional headers
const result = await apiClient.upload('/upload', formData, {
  headers: { 'X-Upload-Type': 'image' },
});

Authentication Helpers

Check if Authenticated

if (apiClient.isAuthenticated()) {
  // User has a valid token
  const data = await apiClient.get('/protected');
}

Get Authentication Info

const authInfo = apiClient.getAuthInfo();
console.log(authInfo.token); // Current token
console.log(authInfo.headers); // Custom headers

Token Management

// Set authentication token
apiClient.setToken('your-auth-token');

// Get current token
const token = apiClient.getToken();

// Clear token
apiClient.clearToken();

Utility Methods

Get RESTful Entity URL

const url = apiClient.getRestfulEntityUrl('/users', { id: 123 });
// Returns: '/users/123'

Get Base URL

const baseUrl = apiClient.getBaseUrl();

Update Base URL

apiClient.setBaseUrl('https://api-v2.example.com');

Access Axios Instance

For advanced use cases, you can access the underlying Axios instance:

const axios = apiClient.getAxiosInstance();

// Use axios directly for custom requests
axios.interceptors.request.use(config => {
  // Custom request interceptor
  return config;
});

Complete API Reference

Methods

| Method | Description | |--------|-------------| | get<T>(path, options?) | Make GET request | | post<T>(path, data?, options?) | Make POST request | | put<T>(path, data?, options?) | Make PUT request | | patch<T>(path, data?, options?) | Make PATCH request | | delete<T>(path, options?) | Make DELETE request | | upload<T>(path, formData, options?) | Upload files with FormData | | setToken(token) | Set authentication token | | getToken() | Get current token | | clearToken() | Clear authentication token | | isAuthenticated() | Check if currently authenticated | | getAuthInfo() | Get current auth info (token + headers) | | getBaseUrl() | Get current base URL | | setBaseUrl(url) | Update base URL | | getRestfulEntityUrl(url, data) | Build RESTful entity URLs | | getAxiosInstance() | Access underlying Axios instance |

Configuration Options

interface ApiClientConfig {
  baseUrl: string;                          // Required: Base URL for all requests
  token?: string;                           // Optional: Initial auth token
  headers?: Record<string, string>;         // Optional: Custom headers
  onUnauthorized?: () => void;              // Optional: 401 error callback
  getToken?: () => string | null;           // Optional: Token getter
  saveToken?: (token: string) => void;      // Optional: Token saver
  clearToken?: () => void;                  // Optional: Token clearer
  axiosConfig?: AxiosRequestConfig;         // Optional: Additional axios config
}

Error Handling

The client automatically handles 401 Unauthorized responses by:

  1. Clearing the stored token
  2. Calling the clearToken callback (if provided)
  3. Calling the onUnauthorized callback (if provided)

For other errors, you can use standard try-catch:

try {
  const data = await apiClient.get('/users');
} catch (error) {
  if (error.response) {
    // Server responded with error status
    console.error('Error:', error.response.status, error.response.data);
  } else if (error.request) {
    // Request made but no response
    console.error('No response received');
  } else {
    // Other errors
    console.error('Error:', error.message);
  }
}

Framework Examples

React

// api.ts
import { ApiClient } from '@uecsio/api-client';

export const apiClient = new ApiClient({
  baseUrl: process.env.REACT_APP_API_URL || 'https://api.example.com',
  getToken: () => localStorage.getItem('token'),
  saveToken: (token) => localStorage.setItem('token', token),
  clearToken: () => localStorage.removeItem('token'),
  onUnauthorized: () => {
    window.location.href = '/login';
  },
});

// In your components
import { apiClient } from './api';

function UsersList() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    apiClient.get('/users').then(setUsers);
  }, []);

  return <div>{/* render users */}</div>;
}

Vue.js

// api.ts
import { ApiClient } from '@uecsio/api-client';
import router from './router';

export const apiClient = new ApiClient({
  baseUrl: process.env.VUE_APP_BASE_API_HOST,
  getToken: () => localStorage.getItem('token'),
  saveToken: (token) => localStorage.setItem('token', token),
  clearToken: () => localStorage.removeItem('token'),
  onUnauthorized: () => {
    router.push({ name: 'Login' });
  },
});

// In your components
import { apiClient } from './api';

export default {
  async mounted() {
    this.users = await apiClient.get('/users');
  },
};

Node.js / Express

import { ApiClient } from '@uecsio/api-client';

const apiClient = new ApiClient({
  baseUrl: 'https://external-api.example.com',
  token: process.env.API_TOKEN,
});

app.get('/proxy/users', async (req, res) => {
  try {
    const users = await apiClient.get('/users');
    res.json(users);
  } catch (error) {
    res.status(500).json({ error: 'Failed to fetch users' });
  }
});

License

MIT