npm package: @ryzes/rio
Description: Axios wrapper for handling { code, message, data } responses and integrating with TanStack React Query.
Author: Ryzes
Latest version: 0.0.8

# @ryzes/rio - Axios Wrapper for Standardized API Responses

⚠️ **IMPORTANT**: This library does not support HTTP status code 3xx redirects. Only 2xx success responses and 4xx/5xx error responses are properly handled.

## Overview

Rio is a TypeScript library that provides an Axios wrapper for handling standardized `{ code, message, data }` API responses and integrates seamlessly with TanStack React Query.

## Installation

```bash
pnpm add @ryzes/rio
# or with npm
npm install @ryzes/rio
# or with yarn
yarn add @ryzes/rio
```

## Quick Start

### 1. Initialize HTTP Client

```typescript
import { httpClient } from '@ryzes/rio';

httpClient.initialize({
  baseURL: 'https://api.example.com',
  timeout: 10000,
  successCode: 0,
});
```

### 2. Use with React Query

```typescript
import { QueryClientProvider } from '@tanstack/react-query';
import { createRioQueryClient } from '@ryzes/rio';
import { httpClient } from '@ryzes/rio';

// Initialize HTTP client
httpClient.initialize({
  baseURL: 'https://api.example.com'
});

// Create React Query client with error handling
const queryClient = createRioQueryClient((title: string, info: string) => {
  // Handle errors globally
  console.error('Error:', title, info);
});

export default function App() {
  return (
    <QueryClientProvider client={queryClient}>
      {/* Your app components */}
    </QueryClientProvider>
  );
}
```

### 3. Make HTTP Requests

```typescript
import { useQuery } from '@tanstack/react-query';
import { httpClient } from '@ryzes/rio';

// In your React component
const MyComponent = () => {
  const { data, isLoading, error } = useQuery({
    queryKey: ['userData'],
    queryFn: async () => {
      // Directly use httpClient.get()
      return httpClient.get<{ name: string; age: number }>('/users/1');
    },
  });

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error: {(error as Error).message}</div>;

  return <div>Hello, {data?.name}!</div>;
};

// Custom error handling with skipGlobalError
const MyComponentWithCustomErrorHandling = () => {
  const { data, isLoading, error } = useQuery({
    queryKey: ['userData'],
    queryFn: async () => {
      // Skip global error handling to handle errors yourself
      return httpClient.get('/users/1', { meta: { skipGlobalError: true } });
    },
  });

  if (isLoading) return <div>Loading...</div>;
  if (error) {
    // Handle error yourself instead of using global error handler
    return <div>Custom error message: {(error as Error).message}</div>;
  }

  return <div>Hello, {data?.name}!</div>;
};
```

### 4. Authentication Support

```typescript
import { ConsoleAuthService } from '@ryzes/rio';

// Initialize with authentication service
httpClient.initialize({
  baseURL: 'https://api.example.com',
  authService: new ConsoleAuthService(),
});

// Login and token handling
interface LoginResponse {
  token: string;
}

const loginResponse = await httpClient.post<LoginResponse>('/auth/login', {
  username: 'your-username',
  password: 'your-password'
});

// Set the authentication token
httpClient.setAuthToken(loginResponse.token);

// Get the current token
const currentToken = httpClient.getAuthToken();

// Clear the token
httpClient.clearAuthToken();
```

## API Reference

### Exported Functions

- `httpClient` - Pre-configured HTTP client instance
- `createRioQueryClient(errorReporter: (title: string, info: string) => void)` - Creates React Query client with built-in error handling

### HttpClient Methods

The `httpClient` instance provides the following HTTP methods:

- `get(url: string, config?: AxiosRequestConfig)` - GET request
- `post(url: string, data: any, config?: AxiosRequestConfig)` - POST request
- `put(url: string, data: any, config?: AxiosRequestConfig)` - PUT request
- `patch(url: string, data: any, config?: AxiosRequestConfig)` - PATCH request
- `delete(url: string, config?: AxiosRequestConfig)` - DELETE request

### Authentication Methods

- `setAuthToken(token: string)` - Set authentication token
- `getAuthToken(): string | null` - Get current authentication token
- `clearAuthToken()` - Clear authentication token

### Raw Response Methods

The library also provides raw response methods that return the complete `{ code, message, data }` structure:

- `getRaw(url: string, config?: AxiosRequestConfig)` - GET request returning raw response
- `postRaw(url: string, data: any, config?: AxiosRequestConfig)` - POST request returning raw response
- `putRaw(url: string, data: any, config?: AxiosRequestConfig)` - PUT request returning raw response
- `patchRaw(url: string, data: any, config?: AxiosRequestConfig)` - PATCH request returning raw response
- `deleteRaw(url: string, config?: AxiosRequestConfig)` - DELETE request returning raw response

### Common Usage Examples

#### Simple GET Request

```typescript
const result = await httpClient.get('/api/users');
```

#### GET Request with Raw Response

```typescript
const rawResponse = await httpClient.getRaw<{ name: string; age: number }>('/api/users/1');
// rawResponse will be: { code: 0, message: 'success', data: { name: 'John', age: 30 } }

// Example with server returning {code:200,message:"ok",data:{result:true}}
const rawResponse = await httpClient.getRaw('/api/example');
// Returns: { code: 200, message: "ok", data: { result: true } }
```

#### POST Request with Data

```typescript
const newUser = await httpClient.post('/api/users', {
  name: 'John Doe',
  email: 'john@example.com'
});
```

#### POST Request with Raw Response

```typescript
const rawResponse = await httpClient.postRaw('/api/users', {
  name: 'John Doe',
  email: 'john@example.com'
});
// rawResponse will be: { code: 0, message: 'success', data: { id: 1, name: 'John', email: 'john@example.com' } }
```

#### Regular Methods vs Raw Methods

**Regular methods** (get, post, put, patch, delete) return only the `data` field from the response:

```typescript
// Server returns: {code:200, message:"ok", data:{result:true}}
const result = await httpClient.get('/api/example');
// Returns: {result: true} (only the data field)
```

**Raw methods** (getRaw, postRaw, putRaw, patchRaw, deleteRaw) return the complete response structure:

```typescript
// Server returns: {code:200, message:"ok", data:{result:true}}
const rawResult = await httpClient.getRaw('/api/example');
// Returns: {code: 200, message: "ok", data: {result: true}} (complete response)
```

#### Request with Query Parameters

```typescript
const users = await httpClient.get('/api/users', {
  params: { page: 1, limit: 10 }
});
```

#### Login and Authentication

```typescript
// Login
const response = await httpClient.post('/auth/login', {
  username: 'testuser',
  password: 'password123'
});

// Set token for future requests
httpClient.setAuthToken(response.token);
```

## Authentication Services

The library supports different authentication service implementations:

- `ConsoleAuthService` - For server-side rendering/console applications (stores tokens in memory)
- `DefaultAuthService` - For browser applications (stores tokens in localStorage)
- Custom services implementing the `AuthService` interface

## Advanced Usage

### Custom Success Code

```typescript
// If your API uses 200 instead of 0 for success
httpClient.initialize({
  baseURL: 'https://api.example.com',
  successCode: 200,
});
```

### Error Handling Integration

```typescript
import { toast } from 'sonner';

const queryClient = createRioQueryClient((title: string, info: string) => {
  toast.error(info); // Show toast notification for errors
});
```

## License

MIT © Ryzes