# Turbium

[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)

Turbium is a **fast**, **efficient**, and **modern** HTTP/2 client library for Node.js designed for high performance and ease of use. It leverages the power of HTTP/2 to provide features like connection pooling, automatic request and response compression, and a straightforward API.

## Key Features

*   **Blazing Fast HTTP/2:** Built on top of the battle-tested `http2-wrapper` library.
*   **Connection Pooling:** Reuses established HTTP/2 connections for improved performance and reduced latency.
*   **Automatic Request/Response Compression:** Supports `gzip`, `deflate`, and `brotli` compression for both requests and responses, significantly reducing bandwidth usage.
*   **DNS Caching:** Caches DNS lookups to minimize latency on subsequent requests.
*   **Built-in Circuit Breaker:** Protects your application from cascading failures by temporarily stopping requests to failing services.
*   **Easy-to-Use API:** Simple and intuitive API inspired by popular libraries like `axios` and `fetch`.
*   **Stream Support:** Handles large responses efficiently with support for streaming.
*   **Highly Configurable:** Fine-tune various aspects of the library to meet your specific needs.
*   **Written in Modern JavaScript:** Leverages ES Modules for a clean and maintainable codebase.

## Installation

```bash
npm install turbium
````

## Usage

### Basic GET Request

```javascript
import turbium from 'turbium';

async function fetchData() {
  try {
    const response = await turbium.get('https://www.npmjs.com/package/turbium');
    console.log('Status:', response.status);
    console.log('Headers:', response.headers);
    console.log('Data:', response.data);
  } catch (error) {
    console.error('Error:', error);
  }
}

fetchData();
```

### POST Request with JSON Data

```javascript
import turbium from 'turbium';

async function postData() {
  try {
    const data = {
      key1: 'value1',
      key2: 'value2',
    };
    const response = await turbium.post('https://www.npmjs.com/package/turbium', data, {
      headers: {
        'Content-Type': 'application/json',
      },
    });
    console.log('Data:', response.data);
  } catch (error) {
    console.error('Error:', error);
  }
}

postData();
```

### Streaming a Response

```javascript
import turbium from 'turbium';
import fs from 'fs';

async function streamData() {
  try {
    const responseStream = await turbium.request({
      url: 'https://www.npmjs.com/package/turbium',
      method: 'GET',
      stream: true,
    });

    const fileStream = fs.createWriteStream('downloaded-file.txt');

    responseStream.on('data', chunk => {
      console.log('Received chunk:', chunk.length, 'bytes');
      fileStream.write(chunk);
    });

    responseStream.on('end', () => {
      console.log('Stream finished.');
      fileStream.end();
    });

    responseStream.on('error', err => {
      console.error('Stream error:', err);
      fileStream.end();
    });

  } catch (error) {
    console.error('Request error:', error);
  }
}

streamData();
```

### Configuration

Turbium can be configured globally or per request.

**Global Configuration:**

```javascript
import turbium from 'turbium';

turbium.config.enableCompression = true;
turbium.config.enableCaching = false;
turbium.config.enableDNSCache = true;
turbium.config.enableCircuitBreaker = true;
turbium.config.maxConcurrentRequests = 100; // Default: Infinity
turbium.config.enableRequestCompression = true;
turbium.config.requestEncoding = 'gzip'; // Default: gzip
```

**Per-Request Configuration:**

```javascript
const response = await turbium.get('[https://example.com](https://example.com)', null, {
  timeout: 5000, // Timeout for this specific request
  enableCaching: true, // Enable caching for this specific request
});
```

## API Reference

### `turbium(urlOrConfig, config)`

  * **`urlOrConfig`** (`string` | `object`): Either the URL to request (string) or a configuration object.
  * **`config`** (`object`): Configuration options (only if `urlOrConfig` is a string).

Returns a `Promise` that resolves with the response object.

### `turbium.request(config)`

  * **`config`** (`object`): The request configuration object.

      * **`url`** (`string`): The URL to make the request to.
      * **`method`** (`string`): The HTTP method (e.g., `GET`, `POST`, `PUT`, `DELETE`). Default: `GET`.
      * **`headers`** (`object`): Request headers.
      * **`data`** (`object` | `string`): The request body.
      * **`body`** (`object` | `string`): Alias for data.
      * **`followRedirects`** (`boolean`): Whether to follow redirects. Default: `true`.
      * **`maxRedirects`** (`number`): The maximum number of redirects to follow. Default: `5`.
      * **`options`** (`object`): Additional HTTP/2 options.
      * **`timeout`** (`number`): Request timeout in milliseconds. Default: `30000`.
      * **`stream`** (`boolean`): Whether to return a stream instead of a buffered response. Default: `false`.
      * **`enableCompression`** (`boolean`): Whether to enable automatic response decompression. Default: `true` (globally configurable).
      * **`enableCaching`** (`boolean`): Whether to enable response caching. Default: `false` (globally configurable).
      * **`enableDNSCache`** (`boolean`): Whether to enable DNS caching. Default: `true` (globally configurable).
      * **`enableCircuitBreaker`** (`boolean`): Whether to enable the circuit breaker. Default: `false` (globally configurable).
      * **`maxConcurrentRequests`** (`number`): Maximum number of concurrent requests allowed. Default: `Infinity` (globally configurable).
      * **`enableRequestCompression`** (`boolean`): Whether to enable request body compression. Default: `false` (globally configurable).
      * **`requestEncoding`** (`string`): Encoding to use for request compression (`gzip`, `deflate`, `br`). Default: `gzip` (globally configurable).

### `turbium.get(url, data, config)`

### `turbium.post(url, data, config)`

### `turbium.put(url, data, config)`

### `turbium.patch(url, data, config)`

### `turbium.delete(url, data, config)`

### `turbium.head(url, data, config)`

### `turbium.options(url, data, config)`

Convenience methods for common HTTP methods. `data` is only applicable for `POST`, `PUT`, and `PATCH`.

**Response Object:**

  * **`data`** (`any`): The response body. If the `Content-Type` is `application/json`, the body will be automatically parsed as JSON.
  * **`status`** (`number`): The HTTP status code.
  * **`statusText`** (`string`): The HTTP status message.
  * **`headers`** (`object`): The response headers.
  * **`config`** (`object`): The configuration object that was used for the request.
  * **`request`** (`object`): The underlying HTTP/2 request object.

## Error Handling

Turbium rejects the Promise with an `Error` object if the request fails. You can catch these errors using `.catch()`.

```javascript
turbium.get('https://www.npmjs.com/package/turbium')
  .catch(error => {
    console.error('Request failed:', error.message);
    if (error.response) {
      // The request was made and the server responded with a status code
      // that falls out of the range of 2xx
      console.error('Status:', error.response.status);
      console.error('Data:', error.response.data);
    } else if (error.request) {
      // The request was made but no response was received
      console.error('No response received:', error.request);
    } else {
      // Something happened in setting up the request that triggered an Error
      console.error('Error:', error.message);
    }
  });
```

## Acknowledgements

This library is built upon the excellent work of the following projects:

  * [http2-wrapper](https://www.google.com/url?sa=E&source=gmail&q=https://github.com/szmarczak/http2-wrapper)
  * [lru-cache](https://www.google.com/url?sa=E&source=gmail&q=https://github.com/isaacs/node-lru-cache)