# 🚀 Nexli (API Request Manager)

[![NPM Version](https://img.shields.io/npm/v/nexli)](https://www.npmjs.com/package/nexli) 
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/hmzatayab/nexli/blob/main/LICENSE) 
[![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
[![Minified Size](https://img.shields.io/bundlephobia/minzip/nexli)](https://bundlephobia.com/package/nexli)
[![NPM Downloads](https://img.shields.io/npm/dt/nexli)](https://www.npmjs.com/package/nexli)

**Nexli** is a powerful, lightweight, and framework-agnostic **API client wrapper** for JavaScript and TypeScript. It abstracts complex network concerns like **retries**, **rate limiting**, **request queuing**, and **offline synchronization** so you can focus on your application logic.

# ✨ Features

* **🛡️ Smart Retries:** Automatic retries on transient server errors (5xx) and timeouts, with configurable backoff.
* **🚦 Rate Limiting:** Controls the request velocity to prevent overwhelming the backend API.
* **📦 Request Queue:** Manages request execution based on **concurrency limits** and **priority**.
* **🔌 Offline Mode:** Automatically persists requests to **Local Storage** when the network is unavailable and syncs them upon reconnection.
* **🌐 Adapter Support:** Compatible with both **Fetch** (default) and **Axios**.
* **✅ Type-Safe:** Fully written in TypeScript for robust integration.



# 📦 Installation

Install Nexli into your project using npm or yarn:

```bash
npm install nexli
# or
yarn add nexli
```
# 🎮 Interactive Demo & Documentation

Don't just take our word for it **see Nexli in action.**

We have built a dedicated **Playground** where you can simulate real-world network chaos.
Toggle **Offline Mode**, trigger **500 Server Errors**, and watch how Nexli's **Priority Queue** and **Auto-Retry System** handle the traffic gracefully.

> ⚡ **Try it out:** Experience the "Chaos Mode" and visualize the Request Queue in real-time.

[![Visit Website](https://img.shields.io/badge/🚀_Launch_Live_Demo_%26_Docs-000?style=for-the-badge&logo=vercel&logoColor=white)](https://nexli.vercel.app/)

[**Explore Full Documentation →**](https://nexli.vercel.app/)

# 🚀 Where Should You Use Nexli? (Backend vs. Frontend)
Nexli is generally **more suitable for Frontend (React/JSX)** applications, but it can also be used in the Backend (Node.js) depending on your needs.

Here is a breakdown of where Nexli is most effective and why:

### 1. ⚛️ Frontend (React, Vue, etc.) - Most Perfect Fit
The core features that make Nexli unique are primarily designed for the browser environment:
| Feature | Reason |
| :--- | :--- |
| **🔌 Offline Mode / Synchronization** | This feature relies on Local Storage (available only in the browser). It automatically saves requests when the user is offline and syncs them upon reconnection. This is a key feature that makes Nexli ideal for the frontend. |
| **🚦 Rate Limiting**  | It helps ensure the client (browser) does not overwhelm the backend API by controlling the request velocity.|
| **📦 Request Queueing** | Managing and prioritizing requests when a user performs many quick actions is a common frontend concern. |
| **🌐 Adapter Support**  | The default adapter is the native Fetch API, which is a browser standard. |

**Conclusion:** If your priority is Offline Synchronization, managing network stability for users, and controlling front-end request queues, Nexli should be used in your React/Frontend code.

### 2. 🟢 Backend (Node.js) - Viable (But Less Necessary)
You can certainly use Nexli in a Node.js environment, especially when configured with the **Axios adapter**.

| Feature | Reason |
| :--- | :--- |
| **🛡️ Smart Retries** | When your Node.js server calls a Third-Party API (like a payment service or data feed), automatic retries on transient server errors (5xx) are highly beneficial for reliability. |
| **📦 Request Queueing**  | If your server needs to send a large volume of requests to a single external service, queueing and concurrency limits can prevent overloading that external API.|
| **🔌 Offline Sync** | This feature will not work out-of-the-box in Node.js, as it relies on the browser's Local Storage. |

**Conclusion:** In the backend, you often have other robust ways to handle retries (e.g., built-in features of libraries like Axios or specific SDKs like the OpenAI one you are using). If you specifically need a unified solution for queueing and advanced retries when talking to other REST APIs, you can use it. However, its biggest advantage (Offline Sync) is lost here.


# 🛠️ Usage Guide

### Step 1: Initialize the Client

Instantiate `ApiClient` with your required configuration.

#### TypeScript
```ts
import { ApiClient } from 'nexli';

const api = new ApiClient({
    // Set the base URL for all requests
    baseUrl: '[https://jsonplaceholder.typicode.com](https://jsonplaceholder.typicode.com)', 
    
    // Configure Queue concurrency
    queue: {
        concurrency: 5, // Process up to 5 requests concurrently
    },
    
    // Configure Rate Limiting (e.g., 5 requests per 2000ms)
    rateLimit: {
        maxRequests: 5,
        perMilliseconds: 2000, 
    },
});
```
### Step 2: Making Requests

Nexli supports all standard HTTP methods (`get`, `post`, `put`, `delete`).

#### **A.** Basic GET Request
#### TypeScript

```ts
async function fetchPost() {
    try {
        const response = await api.get('/posts/1');
        console.log("Post Title:", response.data.title);
    } catch (error) {
        console.error("API Error:", error);
    }
}
fetchPost();
```
#### **B.** POST Request with Priority

You can assign priority to ensure critical requests are processed first in the queue (1 is lowest, 10 is highest).

#### TypeScript

```ts
async function sendHighPriorityLog() {
    const logData = {
        message: 'Critical event occurred!',
        timestamp: Date.now()
    };
    
    // Options are passed as the third argument
    const response = await api.post('/logs', logData, {
        priority: 10 // Highest priority
    });
    
    console.log("Log sent, Status:", response.status);
}
```
### Step 3: Advance Features Setup
#### **A.** Configuring Retry Strategy

Set the maximum attempts and the HTTP status codes that should trigger a retry.

#### TypeScript

```ts
const retryClient = new ApiClient({
    baseUrl: '[https://api.example.com](https://api.example.com)',
    retry: {
        maxAttempts: 4, 
        delayMs: 1000,
        // Only retry on common server/timeout errors
        statusCodes: [500, 503, 408, 429], 
    },
});
```

#### **B.** Offline Synchronization

Enable offline mode to automatically save failed network requests for later synchronization.

#### TypeScript

```ts
const offlineClient = new ApiClient({
    baseUrl: '[https://api.analytics.com](https://api.analytics.com)',
    offline: {
        enabled: true, // Turns on offline storage
        storageKey: 'my_app_pending_requests',
        limit: 50, // Maximum number of requests to store
    },
});

// If the device is offline, this request will be stored and sent later.
offlineClient.post('/analytics', { event: 'checkout_fail' });
```
 **Note:** The synchronization process is triggered automatically upon client initialization. You can manually trigger it using `await client.syncOfflineRequests();`.



# ⚙️ Configuration Options
| Option | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| **`baseUrl`** | `string` | `""` | The root URL for all API requests. |
| **`debug`** | `boolean` | `false` | Enables detailed logs in the console for debugging. |
| **`adapter`** | `'fetch'/'axios'` | `'fetch'` | Network execution engine. |
| **`retry.maxAttempts`** | `number` | `3` | Max number of times to retry on failure. |
| **`queue.concurrency`** | `number` | `5` | Maximum requests processed simultaneously. |
| **`rateLimit.maxRequests`** | `number` | `10` | Max requests allowed in the time window defined by `perMilliseconds`. |
| **`offline.enabled`** | `boolean` | `false` | Enables offline storage and auto-sync using Local Storage. |

# 🤝 Contributing

Contributions are welcome! Please ensure all tests pass before submitting a Pull Request.

* Fork the repository.
* Run the build and tests: `npm run build && npm test`.
* Submit your Pull Request

# 👤 Author & Contributor

This package is maintained and developed by **Hamza Tayyab**. I am passionate about creating clean, efficient, and secure frontend tools. Feel free to connect or check out my other projects!

| Platform | Link |
| :--- | :--- |
| **🌐 Portfolio** | https://linktr.ee/hm.za |
| **📧 Email** | hmzatayab@gmail.com  |
| **💻 GitHub** | Follow me on GitHub https://github.com/hmzatayab |
| **🎁 Other Packages** | Check out my other open-source projects https://www.npmjs.com/~hamzatayab |

# 📄 License
Nexli is released under the MIT License.