gettt
v1.0.0
Published
gettt is a production-ready, fully-featured fetch wrapper for JavaScript and TypeScript. It provides a simple and intuitive API for making HTTP requests, with support for features like request cancellation, retries, and timeouts.
Maintainers
Readme
Gettt
A production-ready, fully-featured HTTP fetch wrapper for JavaScript and TypeScript. Gettt provides a clean, standardized API with built-in retry logic, caching, rate limiting, and comprehensive hook support for seamless integration into any application.
Features
- Standardized Response Format: Consistent
{ data, error, status, headers, meta }structure across all requests - Smart Caching: TTL-based caching with stale-while-revalidate support
- Automatic Retries: Configurable retry attempts with backoff
- Request Deduplication: Automatically deduplicates identical in-flight requests
- Rate Limiting: Built-in token bucket rate limiter
- Circuit Breaker: Prevents cascade failures with automatic circuit breaking
- Authentication: Seamless bearer token injection
- Response Transformation: Built-in response normalization
- Abort Signals: Full AbortController support for request cancellation
- Comprehensive Hooks: Logging hooks for request/response/error/retry/cache events
- TypeScript First: Fully typed with excellent IDE support
Table of Contents
Quick Start
npm install getttimport gettt from 'gettt';
const res = await gettt('/users', { transform: (raw) => raw.items });
console.log(res.data);Installation
npm install gettt
# or
yarn add getttUsage
Basic Example
import gettt from 'gettt';
const res = await gettt('/users', {
transform: (raw) => raw.items, // avoid data.data
retry: { attempts: 3 },
cache: { ttl: 60000, staleWhileRevalidate: true },
dedupe: true
});
if (res.error) console.error('Error:', res.error);
else console.log('Users:', res.data);HTTP Methods
gettt supports all standard HTTP verbs:
const res = await gettt.get('/users');
const res2 = await gettt.post('/users', { body: JSON.stringify({ name: 'Alice' }) });
const res3 = await gettt.put('/users/1', { body: JSON.stringify({ name: 'Bob' }) });
const res4 = await gettt.delete('/users/1');Request Cancellation
const controller = new AbortController();
setTimeout(() => controller.abort(), 2000);
const res = await gettt('/users', { signal: controller.signal });
if (res.error) console.log('Request failed or aborted');
else console.log('Users:', res.data);Response Transformation
Normalize API responses to avoid data.data:
const res = await gettt('/users', {
transform: (raw) => raw.results
});
console.log(res.data); // fully normalizedAPI Reference
Configuration Options
| Option | Type | Description |
| ---------------- | -------------------------------------------------- | ----------------------------------------------------------------------------- |
| baseURL | string | Base URL for all requests |
| headers | Record<string,string> | Default headers |
| retry | { attempts?: number } | Number of retry attempts |
| timeout | number | Timeout per request (ms) |
| auth | { getToken?: () => string \| Promise<string> } | Function to get bearer token |
| cache | { ttl?: number, staleWhileRevalidate?: boolean } | Cache responses |
| dedupe | boolean | Deduplicate identical in-flight requests |
| rateLimit | { max: number, window: number } | Token bucket rate limiter |
| circuitBreaker | { failureThreshold: number, cooldown: number } | Open circuit after failures |
| hooks | object | Logging hooks (onRequest, onResponse, onError, onRetry, onCacheHit) |
| transform | function | Transform raw response data |
| signal | AbortSignal | Abort controller |
Hook System
import { Gettt } from 'gettt';
const api = new Gettt({
hooks: {
onRequest: (ctx) => console.log('Request →', ctx.request.url),
onResponse: (ctx) => console.log('Response ←', ctx.response?.status),
onError: (ctx) => console.error('Error ✖', ctx.error),
onRetry: (ctx) => console.warn('Retry attempt', ctx.meta.attempt),
onCacheHit: (ctx) => console.log('Cache hit for', ctx.request.url)
}
});Response Type
Every request returns a GetttResult:
type GetttResult<T = any> = {
data: T | null;
error: string | null;
status: number;
headers?: Record<string,string>;
meta?: {
attempt: number;
duration: number;
cached?: boolean;
circuitOpen?: boolean;
}
};Advanced Usage
Request Flow
┌──────────────────────┐
│ User calls gettt() │
│ or api.get/post() │
└─────────┬────────────┘
│
▼
┌─────────────────────┐
│ Merge configs & │
│ apply defaults │
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ Circuit Breaker? │
│ (open → abort) │
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ Rate Limit check │
│ (wait if needed) │
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ Deduplication check │
│ (return in-flight) │
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ Cache lookup │
│ (return if hit) │
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ Auth Token inject │
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ Apply AbortSignal │
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ Retry loop │
│ (with timeout) │
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ Fetch API │
└─────────┬───────────┘
│
┌────────────┴────────────┐
│ │
▼ ▼
Success response Network/Error
│ │
▼ ▼
Transform function applied Retry or return error
│
▼
Cache store updated
│
▼
Dedup in-flight cleared
│
▼
Return standardized{ data, error, status, headers, meta }
Production Configuration
import { Gettt } from 'gettt';
const api = new Gettt({
baseURL: 'https://api.example.com',
auth: { getToken: async () => 'mytoken123' },
retry: { attempts: 3 },
cache: { ttl: 60000 },
dedupe: true,
rateLimit: { max: 5, window: 1000 },
circuitBreaker: { failureThreshold: 3, cooldown: 5000 },
transform: (raw) => raw.items,
hooks: {
onRequest: (ctx) => console.log('Requesting:', ctx.request.url),
onResponse: (ctx) => console.log('Received status:', ctx.response?.status)
}
});
const users = await api.get('/users');
console.log(users.data);Why Gettt?
Gettt solves common HTTP client pain points:
- No more
data.data: Standardized response format prevents data structure inconsistencies - Production-ready out of the box: Built-in retry logic, circuit breaker, and rate limiting
- Request intelligence: Automatic deduplication and caching eliminate redundant network calls
- Better debugging: Comprehensive hook system provides visibility into request lifecycle
- Developer experience: Fully typed API with excellent TypeScript support
License
MIT License © 2026 Han Lin Yap
