Guide

API Reference

Reference documentation for the @docyrus/api-client — type-safe REST client with streaming, token management, and error handling.

The @docyrus/api-client is a modern, type-safe API client for JavaScript and TypeScript. It works across Web, React Native, and Node.js.

Installation

pnpm add @docyrus/api-client

Quick Start

import { RestApiClient } from '@docyrus/api-client';

const client = new RestApiClient({
  baseUrl: 'https://api.example.com',
  getAccessToken: () => getToken(),
});

// GET request
const users = await client.get('/v1/users');

// POST with body
const user = await client.post('/v1/users', {
  body: { name: 'Ali', email: 'ali@example.com' },
});

Client Configuration

const client = new RestApiClient({
  baseUrl: string;              // API base URL (required)
  getAccessToken: () => Promise<string | null>;  // Token provider
  refreshToken?: () => Promise<string | null>;   // Auto-refresh on 401
  onUnauthorized?: () => void;  // Callback when auth fails
  headers?: Record<string, string>;  // Default headers
  timeout?: number;             // Request timeout (ms)
});
OptionTypeRequiredDescription
baseUrlstringYesAPI base URL
getAccessToken() => Promise<string | null>YesReturns current access token
refreshToken() => Promise<string | null>NoCalled on 401 — refreshes token and retries
onUnauthorized() => voidNoCalled when both token and refresh fail
headersRecord<string, string>NoDefault headers for every request
timeoutnumberNoRequest timeout in milliseconds

HTTP Methods

GET

// Simple GET
const data = await client.get('/v1/users');

// With query parameters
const data = await client.get('/v1/users', {
  params: { page: 1, limit: 20, search: 'Ali' },
});

// With type safety
interface User { id: string; name: string; email: string }
const users = await client.get<User[]>('/v1/users');

POST

const user = await client.post<User>('/v1/users', {
  body: { name: 'Ali', email: 'ali@example.com' },
});

PUT / PATCH

await client.put('/v1/users/123', {
  body: { name: 'Updated Name' },
});

await client.patch('/v1/users/123', {
  body: { email: 'new@example.com' },
});

DELETE

await client.delete('/v1/users/123');

Streaming

For real-time data and server-sent events:

const stream = client.stream('/v1/chat/completions', {
  method: 'POST',
  body: { message: 'Hello', model: 'gpt-4' },
});

for await (const chunk of stream) {
  console.log(chunk); // Process each chunk as it arrives
}

Error Handling

import { ApiError } from '@docyrus/api-client';

try {
  await client.post('/v1/users', { body: userData });
} catch (error) {
  if (error instanceof ApiError) {
    console.log(error.status);   // HTTP status code
    console.log(error.message);  // Error message
    console.log(error.data);     // Response body
  }
}
PropertyTypeDescription
statusnumberHTTP status code (400, 401, 404, 500, etc.)
messagestringError message from the server
dataunknownFull response body

Token Management

The client handles token refresh automatically:

  1. Request fails with 401 Unauthorized
  2. Client calls refreshToken() to get a new token
  3. Original request is retried with the new token
  4. If refresh also fails, onUnauthorized() is called
const client = new RestApiClient({
  baseUrl: 'https://api.example.com',
  getAccessToken: () => tokenStore.getAccessToken(),
  refreshToken: async () => {
    const newToken = await authService.refresh();
    tokenStore.setAccessToken(newToken);
    return newToken;
  },
  onUnauthorized: () => {
    // Redirect to login
    router.push('/login');
  },
});

Usage with React

With TanStack Query

import { useQuery, useMutation } from '@tanstack/react-query';

function useUsers() {
  const client = useApiClient(); // Your custom hook

  return useQuery({
    queryKey: ['users'],
    queryFn: () => client.get<User[]>('/v1/users'),
  });
}

function useCreateUser() {
  const client = useApiClient();

  return useMutation({
    mutationFn: (data: CreateUserInput) =>
      client.post<User>('/v1/users', { body: data }),
  });
}

With React Native

The API client works identically in React Native — no additional configuration needed:

import { RestApiClient } from '@docyrus/api-client';
import * as SecureStore from 'expo-secure-store';

const client = new RestApiClient({
  baseUrl: 'https://api.example.com',
  getAccessToken: () => SecureStore.getItemAsync('access_token'),
});
  • Packages — All @docyrus/* NPM packages
  • CLI — Authentication and project setup commands

On this page