@nlabs/rip-hunter
Version:
JS utilities for AJAX and GraphQL
419 lines (306 loc) β’ 11.1 kB
Markdown
# Rip Hunter: HTTP Client for REST & GraphQL**
> **Rip Hunter: Your Universal Gateway to Modern API Endpoints with Unmatched Speed and Reliability**
[](https://www.npmjs.com/package/rip-hunter)
[](https://www.npmjs.com/package/rip-hunter)
[](https://github.com/nitrogenlabs/rip-hunter/issues)
[](https://github.com/ellerbrock/typescript-badges/)
[](http://opensource.org/licenses/MIT)
[](https://discord.gg/Ttgev58)
**rip-hunter** is the all-in-one HTTP utility for developers who want a seamless, ESM-first way to connect to REST and GraphQL APIs. Whether you're building in Node.js, the browser, or serverless, rip-hunter makes data fetching, mutations, and error handling effortlessβso you can focus on building features, not plumbing.
---
## Why rip-hunter?
- **Unified API**: One package for both REST and GraphQL endpoints
- **ESM & TypeScript Native**: Modern, type-safe, and tree-shakable
- **Works Everywhere**: Node, browser, serverlessβno config needed
- **Built-in Auth & Headers**: Effortlessly add tokens and custom headers
- **Automatic Error Handling**: Consistent, developer-friendly errors
- **Tiny & Fast**: Minimal dependencies, zero bloat
- **Request Caching**: Built-in caching for GET requests
- **Timeout Support**: Configurable request timeouts
- **Request Deduplication**: Prevents duplicate requests
- **Real-time Updates**: Server-Sent Events (SSE) support
- **GraphQL Subscriptions**: WebSocket-based subscriptions with automatic reconnection
---
## Installation
```bash
npm install @nlabs/rip-hunter
# or
yarn add @nlabs/rip-hunter
# For Node.js SSE support (optional)
npm install eventsource
```
---
## β‘ Quick Start
### REST Example
```js
import { get, post } from '@nlabs/rip-hunter';
const url = 'https://api.example.com/data';
// GET request with caching
const data = await get(url, { userId: 123 }, { cache: true });
// POST request with auth token and timeout
const result = await post(url, { name: 'Rip Hunter' }, {
token: 'your_jwt_token',
timeout: 5000
});
```
### GraphQL Example
```js
import { query, mutation, toGql } from '@nlabs/rip-hunter';
const url = 'https://api.example.com/graphql';
const gql = '{ user { id name } }';
// Query with timeout
const userData = await query(url, gql, { timeout: 10000 });
// Mutation with variables
const input = { name: 'Rip Hunter' };
const mutationGql = `mutation { createUser(input: ${toGql(input)}) { id name } }`;
const created = await mutation(url, mutationGql, { timeout: 5000 });
```
### GraphQL Subscription Example
```js
import { subscribe } from '@nlabs/rip-hunter';
// Subscribe to real-time GraphQL updates
const unsubscribe = subscribe(
'wss://api.example.com/graphql',
`
subscription {
userUpdated {
id
name
email
}
}
`,
{
onNext: (data) => {
console.log('User updated:', data.userUpdated);
},
onError: (error) => {
console.error('Subscription error:', error);
},
onComplete: () => {
console.log('Subscription completed');
},
onReconnect: (attempt) => {
console.log(`Reconnecting... (attempt ${attempt})`);
}
},
{
token: 'your_jwt_token',
variables: { userId: '123' },
connectionParams: { clientId: 'my-client' },
maxReconnectAttempts: 10,
reconnectInterval: 1000
}
);
// Later, to unsubscribe:
unsubscribe();
```
### SSE Example
```js
import { subscribeSSE } from '@nlabs/rip-hunter';
// Subscribe to real-time updates
const unsubscribe = subscribeSSE('https://api.example.com/stream', {
onMessage: (event) => {
console.log('Received:', event.data);
},
onError: (error) => {
console.error('SSE Error:', error);
},
onOpen: () => {
console.log('SSE connection opened');
}
}, {
token: 'your_jwt_token',
timeout: 30000,
retryInterval: 1000,
maxRetries: 5
});
// Later, to stop listening:
unsubscribe();
```
---
## π οΈ API Reference
### REST Functions
#### `ajax(url, method, params?, options?)`
Low-level HTTP request for any method.
- **url**: `string` β Absolute URL
- **method**: `string` β HTTP method (GET, POST, etc.)
- **params**: `object` β Data to send (query for GET, body for others)
- **options**: `{ headers?, token?, timeout?, cache? }`
- **Returns**: `Promise<any>`
#### `get(url, params?, options?)`
HTTP GET request.
- **url**: `string`
- **params**: `object`
- **options**: `{ headers?, token?, timeout?, cache? }`
- **Returns**: `Promise<any>`
#### `post(url, params?, options?)`
HTTP POST request.
- **url**: `string`
- **params**: `object`
- **options**: `{ headers?, token?, timeout? }`
- **Returns**: `Promise<any>`
#### `put(url, params?, options?)`
HTTP PUT request.
- **url**: `string`
- **params**: `object`
- **options**: `{ headers?, token?, timeout? }`
- **Returns**: `Promise<any>`
#### `del(url, params?, options?)`
HTTP DELETE request.
- **url**: `string`
- **params**: `object`
- **options**: `{ headers?, token?, timeout? }`
- **Returns**: `Promise<any>`
---
### GraphQL Functions
#### `query(url, body, options?)`
Send a GraphQL query.
- **url**: `string` β GraphQL endpoint
- **body**: `string` β GraphQL query string
- **options**: `{ headers?, token?, variables?, stripWhitespace?, timeout? }`
- **Returns**: `Promise<any>`
#### `mutation(url, body, options?)`
Send a GraphQL mutation.
- **url**: `string`
- **body**: `string`
- **options**: `{ headers?, token?, variables?, stripWhitespace?, timeout? }`
- **Returns**: `Promise<any>`
#### `subscribe(url, query, callbacks, options?)`
Subscribe to a GraphQL subscription over WebSocket (graphql-ws protocol).
- **url**: `string` β WebSocket URL (ws:// or wss://)
- **query**: `string` β GraphQL subscription query string
- **callbacks**: `HunterSubscriptionCallbackType` β Event handlers
- `onNext?: (data: any) => void` β Called when new data arrives
- `onError?: (error: Error | Event) => void` β Called on errors
- `onComplete?: () => void` β Called when subscription completes
- `onReconnect?: (attempt: number) => void` β Called during reconnection attempts
- **options**: `HunterSubscriptionOptionsType`
- `token?: string` β Authentication token
- `variables?: Record<string, unknown>` β GraphQL variables
- `connectionParams?: Record<string, unknown>` β WebSocket connection parameters
- `maxReconnectAttempts?: number` β Maximum reconnection attempts (default: 5)
- `reconnectInterval?: number` β Delay between reconnection attempts in ms (default: 1000)
- `timeout?: number` β Connection timeout
- `headers?: Headers` β Custom headers
- **Returns**: `() => void` β Unsubscribe function
#### `graphqlQuery(url, query, options?)`
Low-level GraphQL request.
- **url**: `string` β GraphQL endpoint
- **query**: `HunterQueryType | HunterQueryType[]` β Query object(s)
- **options**: `{ headers?, token?, timeout? }`
- **Returns**: `Promise<any>`
#### `toGql(data)`
Convert JS objects, arrays, or primitives to GraphQL input strings.
- **data**: `any`
- **Returns**: `string`
- **Example**:
```js
toGql({ name: 'Rip', age: 42 }) // => '{name: "Rip", age: 42}'
```
---
### SSE Functions
#### `subscribeSSE(url, callbacks, options?)`
Subscribe to Server-Sent Events.
- **url**: `string` β SSE endpoint URL
- **callbacks**: `HunterSSECallbackType` β Event handlers
- `onMessage?: (event: HunterSSEEventType) => void`
- `onOpen?: (event: Event) => void`
- `onError?: (error: Error | Event) => void`
- `onRetry?: (attempt: number, delay: number) => void`
- **options**: `HunterSSEOptionsType` β Connection options
- `headers?: Headers`
- `token?: string`
- `timeout?: number` (default: 30000)
- `retryInterval?: number` (default: 1000)
- `maxRetries?: number` (default: 5)
- **Returns**: `() => void` β Cleanup function
#### `HunterSSEEventType`
SSE event object with:
- `data: string` β Event data
- `type: string` β Event type
- `id?: string` β Event ID
- `retry?: number` β Retry interval (if specified by server)
---
### Events & Error Handling
#### `on(eventType, listener)`
Subscribe to events (e.g., error events).
- **eventType**: `string` (e.g., 'rip_hunter_error')
- **listener**: `Function`
#### `off(eventType, listener)`
Unsubscribe from events.
#### `ApiError`
All errors are wrapped in a consistent `ApiError` object for easy handling.
- **.errors**: `string[]` β List of error messages
- **.source**: `Error` β Original error object
---
## Advanced Usage
### Request Caching
```js
// Cache GET requests for 5 minutes
const data = await get('/api/users', {}, { cache: true });
```
### Timeout Handling
```js
// Set 10 second timeout
const result = await post('/api/data', payload, { timeout: 10000 });
```
### Custom Headers
```js
const headers = new Headers({
'X-Custom-Header': 'value',
'Content-Type': 'application/json'
});
const data = await get('/api/data', {}, { headers });
```
### GraphQL Variables
```js
const query = `
query GetUser($id: ID!) {
user(id: $id) { name email }
}
`;
const variables = { id: '123' };
const user = await query('/graphql', query, { variables });
```
### SSE with Authentication
```js
const headers = new Headers({
'Authorization': 'Bearer your-token',
'Accept': 'text/event-stream'
});
const unsubscribe = subscribeSSE('/api/notifications', {
onMessage: (event) => {
const notification = JSON.parse(event.data);
console.log('New notification:', notification);
},
onError: (error) => {
console.error('SSE error:', error);
}
}, {
headers,
timeout: 60000,
maxRetries: 10
});
```
---
## Performance Features
- **Request Deduplication**: Prevents duplicate requests to the same endpoint
- **Built-in Caching**: Automatic caching for GET requests with 5-minute TTL
- **Timeout Support**: Configurable request timeouts (default: 30s)
- **Optimized Functions**: Lightweight utility functions for better performance
- **Memory Efficient**: Minimal object creation and garbage collection
- **SSE Reconnection**: Automatic retry with exponential backoff for SSE connections
---
## Environment Support
- **Browser**: Full support for all features including SSE
- **Node.js**: Full REST/GraphQL support, SSE requires `eventsource` package
- **Serverless**: REST/GraphQL support (SSE not recommended in serverless)
---
## Contributing
PRs and issues welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
## License
MIT Β© Nitrogen Labs, Inc.
## π Links
- [GitHub](https://github.com/nitrogenlabs/rip-hunter)
- [NPM](https://www.npmjs.com/package/rip-hunter)