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-clientQuick 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)
});| Option | Type | Required | Description |
|---|---|---|---|
baseUrl | string | Yes | API base URL |
getAccessToken | () => Promise<string | null> | Yes | Returns current access token |
refreshToken | () => Promise<string | null> | No | Called on 401 — refreshes token and retries |
onUnauthorized | () => void | No | Called when both token and refresh fail |
headers | Record<string, string> | No | Default headers for every request |
timeout | number | No | Request 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
}
}| Property | Type | Description |
|---|---|---|
status | number | HTTP status code (400, 401, 404, 500, etc.) |
message | string | Error message from the server |
data | unknown | Full response body |
Token Management
The client handles token refresh automatically:
- Request fails with
401 Unauthorized - Client calls
refreshToken()to get a new token - Original request is retried with the new token
- 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'),
});