axios-wrapped
Version:
A wrapped version of Axios with additional functionality
377 lines (301 loc) • 10.9 kB
Markdown
# 🚀 Axios Wrapped
[](https://www.npmjs.com/package/axios-wrapped)
[](https://bundlephobia.com/package/axios-wrapped)
[](https://opensource.org/licenses/MIT)
[](https://www.typescriptlang.org/)
> Making HTTP requests that don't make you want to pull your hair out!
A fluent, chainable HTTP client builder for Node.js and browsers, built on top of Axios. Because life's too short for messy request configs.
## Why Axios Wrapped?
Ever looked at your API code and thought it resembled spaghetti more than JavaScript? Us too! That's why we created `axios-wrapped` - to bring some sanity back to your HTTP requests.
```javascript
// Before: "What was I even trying to do here?"
axios({
method: 'post',
url: 'https://api.example.com/posts',
headers: { 'Authorization': 'Bearer ' + token, 'X-API-Version': '2.0' },
params: { source: 'web' },
data: { title: 'API calls should be fun', content: '...but they rarely are' }
}).then(res => console.log(res.data)).catch(err => console.error('Oops!', err));
// After: "Oh, that's actually readable!"
new Request('https://api.example.com')
.setMethod(EHttpMethod.Post)
.setEndpoint('/posts')
.addHeader('Authorization', `Bearer ${token}`)
.addHeader('X-API-Version', '2.0')
.addQueryParam('source', 'web')
.setBody({
title: 'API calls should be fun',
content: '...and now they are!'
})
.build()
.execute()
.then(data => console.log(data))
.catch(err => console.error('Still oops, but at least the code looks nice!', err));
```
## ✨ Features That Will Make Your Day Better
- **Chain All The Things**: Write requests that actually make sense when you read them
- **TypeScript Love**: Full TypeScript support because `any`'s are scary
- **Smart Retries**: Auto-retry failed requests without copy-pasting code everywhere
- **Hook It Up**: Add success and error hooks like you're setting up event listeners
- **Be Flexible**: Handle dates, objects, and arrays in headers/params without breaking a sweat
- **Parameter Power**: Manage URL params, query params, and body params with equal ease
- **Instance Control**: Bring your own Axios instance with custom configs
- **Header Happiness**: Manage headers like a boss with easy get/set/remove operations
- **Date Magic**: Automatic date formatting for query parameters and headers
- **Bulk Operations**: Set multiple headers/params at once because your time is precious
## 📦 Installation (It's Easy, Promise!)
```bash
npm install axios axios-wrapped
```
## ⚡ Quick Start (Even Quicker Than Instant Ramen)
```typescript
import { Request, EHttpMethod } from 'axios-wrapped';
// Fetch users without losing your will to live
const users = await new Request('https://api.example.com')
.setMethod(EHttpMethod.Get)
.setEndpoint('/users')
.addQueryParam('page', '1')
.build()
.execute();
console.log(users); // Look ma, no response.data!
```
## 🧩 Core Concepts (Don't Worry, They're Simple)
### Method Chaining (Like LEGO, But For Code)
```typescript
const builder = new Request('https://api.example.com')
.setMethod(EHttpMethod.Post)
.setContentType('application/json')
.addHeader('Authorization', `Bearer ${token}`)
.setBody({ message: "This is so much cleaner than a config object!" });
```
### Parameter Magic (Different Kinds, Same Easy Syntax)
```typescript
// Query params (after the ?)
builder.addQueryParam('include', 'details');
builder.addQueryParam('limit', '10');
// Multiple at once? No problem!
builder.setQueryParams({
sort: 'desc',
fields: 'name,email'
});
```
### Date Formatting (Because Dates Are Hard)
```typescript
// "Give me all orders from last week"
const lastWeek = new Date();
lastWeek.setDate(lastWeek.getDate() - 7);
builder.addQueryParam(
'createdAfter',
lastWeek,
date => date.toISOString() // Format however you want!
);
```
### Request Cancellation (Stop It Right Now!)
Sometimes you need to pull the plug on a request—like when a user navigates away or a timeout kicks in. Use `abort()` to cancel a request before it completes.
```typescript
const builder = new Request('https://api.example.com')
.setEndpoint('/slow-endpoint')
.build();
builder.execute();
setTimeout(() => builder.abort(), 2000); // Cancel after 2 seconds
```
### Hooks (For When Things Go Right or Wrong)
```typescript
builder
.addOnSuccessHook(response => {
console.log('Woohoo! Status:', response.status);
return { retry: false }; // We're good!
})
.addOnErrorHook(async (error, builder) => {
console.error('Dang it:', error.message);
// Token expired? No problem!
if (error.response?.status === 401) {
const newToken = await refreshToken();
builder.addHeader('Authorization', `Bearer ${newToken}`);
return { retry: true }; // Let's try again
}
return { retry: false }; // I give up
});
```
## 🛠️ Complete API Reference (Because You're a Power User)
### URL & Endpoint Management
```typescript
const request = new Request('https://api.example.com');
// Get/Set base URL
request.getUrl(); // 'https://api.example.com'
request.setUrl('https://api2.example.com');
// Get/Set endpoint
request.setEndpoint('/users');
request.getEndpoint(); // '/users'
// Get/Set HTTP method
request.setMethod(EHttpMethod.Post);
request.getMethod(); // EHttpMethod.Post
```
### Header Management (Because Headers Matter)
```typescript
// Content-Type shortcuts
request.setContentType('application/json');
request.getContentType(); // 'application/json'
// Single header operations
request.addHeader('Authorization', 'Bearer token123');
request.getHeader('Authorization'); // 'Bearer token123'
request.hasHeader('X-API-Key'); // false
request.removeHeader('X-Temp-Header');
// Bulk header operations
request.setHeaders({
'X-Client': 'WebApp',
'Accept-Language': 'en-US'
});
// Date headers with custom formatting
request.addHeader('Expires', new Date(), date => date.toUTCString());
```
### Parameter Management (For That URL Magic)
```typescript
// Single parameter
request.addParam('id', '123');
request.getParam('id'); // '123'
request.hasParam('id'); // true
request.removeParam('id');
// Bulk parameters
request.setParams({
userId: '456',
role: 'admin'
});
// Date parameters
request.addParam('expiresAt', new Date(), date => date.getTime().toString());
```
### Query Parameter Management (The ? Stuff)
```typescript
// Single query param
request.addQueryParam('page', '2');
request.getQueryParam('page'); // '2'
request.hasQueryParam('page'); // true
request.removeQueryParam('page');
// Bulk query params
request.setQueryParams({
limit: '10',
sort: 'desc'
});
// Array query params
request.addQueryParam('tags', ['js', 'ts', 'axios']);
// Date query params
request.addQueryParam('createdBefore', new Date(), date => date.toISOString());
```
### Body Management (Where the Meat Goes)
```typescript
// Set and check body
request.setBody({ title: 'Hello World' });
request.getBody(); // { title: 'Hello World' }
request.hasBody(); // true
```
### Hooks (For Those Special Moments)
```typescript
// Success hook
request.addOnSuccessHook(async (response) => {
console.log('Success!', response.status);
return { retry: false };
});
// Error hook with retry logic
request.addOnErrorHook(async (error, builder) => {
if (error.response?.status === 429) {
await new Promise(resolve => setTimeout(resolve, 1000));
return { retry: true };
}
return { retry: false };
});
```
### Execution (Make It So!)
```typescript
// Build with TypeScript generics
interface User {
id: number;
name: string;
}
const executable = request.build<User>();
// Execute and get typed response
const user = await executable.execute();
console.log(user.name); // TypeScript knows this is a string!
```
## 🔍 Common Request Patterns (Copy-Paste These, We Won't Judge)
### Create a New Thing
```typescript
const post = await new Request('https://api.example.com')
.setMethod(EHttpMethod.Post)
.setEndpoint('/posts')
.setBody({
title: 'Axios Wrapped Rocks',
content: 'No, seriously, it does.',
})
.build()
.execute();
```
### Get a Thing with Type Safety
```typescript
interface User {
id: number;
name: string;
email: string;
}
const user = await new Request('https://api.example.com')
.setMethod(EHttpMethod.Get)
.setEndpoint('/users/123')
.build<User>() // Look ma, type safety!
.execute();
console.log(user.name); // TypeScript knows this is a string!
```
### Update a Thing with Automatic Retry
```typescript
const updatedPost = await new Request('https://api.example.com')
.setMethod(EHttpMethod.Patch)
.setEndpoint('/posts/123')
.setBody({ title: 'Updated Title' })
.addOnErrorHook(async (error, builder) => {
// Server having a bad day? Give it another chance
if (error.response?.status >= 500) {
// Wait a second before retry
await new Promise(resolve => setTimeout(resolve, 1000));
return { retry: true };
}
return { retry: false };
})
.build()
.execute();
```
### Delete a Thing
```typescript
await new Request('https://api.example.com')
.setMethod(EHttpMethod.Delete)
.setEndpoint('/posts/123')
.build()
.execute();
console.log('Goodbye, post 123! 👋');
```
### Custom Axios Instance (When You Need Extra Control)
```typescript
// Create an Axios instance with custom settings
const instance = axios.create({
timeout: 5000,
withCredentials: true
});
// Use it with your request
const response = await new Request('https://api.example.com', instance)
.setMethod(EHttpMethod.Get)
.setEndpoint('/users')
.build()
.execute();
```
## 💡 Pro Tips
1. **Debug More Easily**: Each step in the chain is clear, making it easier to spot issues
2. **Handle 401s Gracefully**: Use error hooks to refresh tokens and retry
3. **Keep It DRY**: Create base request builders for common API patterns
4. **Format Those Dates**: Use the date formatter to ensure consistent date formats
5. **Type Everything**: Use TypeScript generics for type-safe responses
6. **Bulk It Up**: Use `setHeaders` and `setParams` to configure multiple values at once
7. **Hook It**: Add logging or analytics in your hooks for cross-cutting concerns
8. **Check Before You Get**: Use `hasHeader`/`hasParam` to avoid undefined errors
## 👨💻 Contributing
## 👨💻 Contributing
Got ideas to make `axios-wrapped` even cooler? We’re open to contributions—jump in and join the fun! 🎉 See [CONTRIBUTING.md](./CONTRIBUTING.md).
## 📄 License
MIT © [Sahil Multani]
*Because coding HTTP requests should be fun, not painful.*