mesh-fetcher
Version:
A Node.js package for fetching data from multiple APIs with enhanced features.
375 lines (273 loc) • 10.9 kB
Markdown
"center">

<h2>A Modern TypeScript Utility Library for API Fetching and Data Manipulation</h2>
[](https://www.npmjs.com/package/mesh-fetcher)
[](https://www.npmjs.com/package/mesh-fetcher)
[](https://www.typescriptlang.org/)
[](https://opensource.org/licenses/MIT)
</div>
<div align="center">
<p><strong>Elegant, type-safe utilities for modern web development</strong></p>
<p>Simplify API interactions, data transformations, and string manipulations with a lightweight, zero-dependency library</p>
</div>
<div align="center">
<p>
<a href="EXAMPLE.md">
<img src="https://img.shields.io/badge/📚_Comprehensive_Guide-View_Examples-40B883?style=for-the-badge" alt="View Examples" />
</a>
</p>
<p><sub>Explore our comprehensive guide with real-world examples and best practices</sub></p>
</div>
<table>
<tr>
<td width="25%">
<h3 align="center">🌐 Network</h3>
<p align="center">
<code>fetchAPI</code> • <code>fetchAPIWithRetry</code><br/>
<code>formatResponse</code> • <code>debounce</code> • <code>throttle</code> • <code>fetchWithCasche</code>
</p>
</td>
<td width="25%">
<h3 align="center">🔄 Arrays</h3>
<p align="center">
<code>uniqueArray</code> • <code>mergeArrays</code><br/>
<code>flattenArray</code> • <code>chunkArray</code>
</p>
</td>
<td width="25%">
<h3 align="center">📝 Strings</h3>
<p align="center">
<code>truncateString</code> • <code>capitalizeWords</code><br/>
<code>slugify</code>
</p>
</td>
<td width="25%">
<h3 align="center">🔧 Objects</h3>
<p align="center">
<code>deepClone</code> • <code>deepEqual</code><br/>
<code>mergeObjects</code> • <code>flattenObject</code><br/>
<code>pick</code> • <code>omit</code>
</p>
</td>
</tr>
</table>
```bash
npm install mesh-fetcher
yarn add mesh-fetcher
pnpm add mesh-fetcher
```
```typescript
import { fetchAPI, debounce, fetchWithCache } from 'mesh-fetcher';
// Simple API fetch with error handling
const getData = async () => {
const response = await fetchAPI('https://api.example.com/data');
console.log(response);
};
// Debounced API call
const debouncedFetch = debounce(getData, 300);
// Cached API call with multiple cache strategies
const getCachedData = async () => {
// Using memory cache (default)
const memoryData = await fetchWithCache('https://api.example.com/data', {
cacheTTL: 1000 * 60 * 5, // 5 minutes cache
cacheType: 'memory',
});
// Using LRU cache
const lruData = await fetchWithCache('https://api.example.com/data', {
cacheType: 'lru',
forceRefresh: false, // Use cached data if available
});
// Using persistent cache (localStorage)
const persistentData = await fetchWithCache('https://api.example.com/data', {
cacheType: 'persistent',
storage: 'localStorage',
cacheTTL: 1000 * 60 * 60 * 24, // 24 hours cache
});
};
```
```typescript
import { uniqueArray, flattenArray, chunkArray } from 'mesh-fetcher';
// Remove duplicates
const unique = uniqueArray([1, 2, 2, 3, 3, 4]); // [1, 2, 3, 4]
// Flatten nested arrays
const flat = flattenArray([1, [2, 3], [4, [5, 6]]]); // [1, 2, 3, 4, 5, 6]
// Create chunks
const chunks = chunkArray([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]
```
```typescript
import { truncateString, capitalizeWords, slugify } from 'mesh-fetcher';
// Truncate long text
const truncated = truncateString('This is a long sentence that needs truncating', 20);
// "This is a long..."
// Capitalize words
const capitalized = capitalizeWords('hello world'); // "Hello World"
// Create URL-friendly slugs
const slug = slugify('Hello World & Special Characters!'); // "hello-world-and-special-characters"
const customSlug = slugify('Hello World', { replacement: '_', strict: true }); // "hello_world"
```
```typescript
import { deepClone, deepEqual, mergeObjects, flattenObject, pick, omit } from 'mesh-fetcher';
// Deep clone objects with circular references
const obj = {
date: new Date(),
map: new Map([['key', 'value']]),
nested: { array: [1, 2, { x: 1 }] },
};
const clone = deepClone(obj);
// Deep equality comparison
const obj1 = { a: 1, b: { x: [1, 2] } };
const obj2 = { a: 1, b: { x: [1, 2] } };
const isEqual = deepEqual(obj1, obj2); // true
// Merge objects deeply
const target = { a: 1, b: { x: 1 } };
const source = { b: { y: 2 }, c: 3 };
const merged = mergeObjects(target, source);
// { a: 1, b: { x: 1, y: 2 }, c: 3 }
// Flatten nested objects
const nested = {
user: {
name: 'John',
address: { city: 'NY' },
},
};
const flat = flattenObject(nested);
// { 'user.name': 'John', 'user.address.city': 'NY' }
// Pick specific properties
const user = { name: 'John', age: 30, password: '123' };
const public = pick(user, ['name', 'age']);
// { name: 'John', age: 30 }
// Omit specific properties
const safe = omit(user, ['password']);
// { name: 'John', age: 30 }
```
Truncate a string to a specified length with customizable options:
```typescript
truncateString(str, maxLength, options);
```
**Options:**
- `replacement`: String to use as replacement (default: "...")
- `wordBoundary`: Whether to truncate at word boundaries (default: false)
- `position`: Where to truncate - 'start', 'middle', or 'end' (default: "end")
### `capitalizeWords`
Capitalize words in a string with customizable options:
```typescript
capitalizeWords(str, options);
```
**Options:**
- `preserveCase`: Whether to preserve existing case in rest of word (default: false)
- `excludeWords`: Words to exclude from capitalization (default: [])
- `locale`: Locale to use for capitalization (default: undefined)
- `onlyFirstWord`: Whether to capitalize only the first word (default: false)
### `slugify`
Convert a string to a URL-friendly slug with customizable options:
```typescript
slugify(str, options);
```
**Options:**
- `replacement`: Character to use for spaces/special chars (default: "-")
- `lower`: Convert the slug to lowercase (default: true)
- `trim`: Remove leading and trailing spaces (default: true)
- `strict`: Remove all special characters (default: true)
- `transliterate`: Convert accented characters to ASCII (default: true)
- `maxLength`: Maximum length of the generated slug
- `customReplacements`: Custom character mappings
## 📘 Object Utilities API
### `deepClone`
Create a deep clone of an object with support for special types and circular references:
```typescript
deepClone(obj, options);
```
**Options:**
- `maxDepth`: Maximum depth for recursive operations (default: Infinity)
- `preservePrototype`: Whether to preserve prototype chain (default: false)
- `includeNonEnumerable`: Whether to include non-enumerable properties (default: false)
### `deepEqual`
Perform a deep equality comparison between two values:
```typescript
deepEqual(a, b, options);
```
**Options:**
- `maxDepth`: Maximum depth for comparison (default: Infinity)
- `includeNonEnumerable`: Whether to include non-enumerable properties (default: false)
### `mergeObjects`
Deeply merge two objects with configurable behavior:
```typescript
mergeObjects(target, source, options);
```
**Options:**
- `arrayMerge`: How to handle arrays ('replace' | 'concat' | 'union') (default: 'replace')
- `clone`: Whether to clone objects during merge (default: true)
- `maxDepth`: Maximum depth for merging (default: Infinity)
- `preservePrototype`: Whether to preserve prototype chain (default: false)
### `flattenObject`
Convert a nested object structure into a flat object with dot notation:
```typescript
flattenObject(obj, options);
```
**Options:**
- `delimiter`: Character to use as delimiter in keys (default: ".")
- `maxDepth`: Maximum depth to flatten (default: Infinity)
- `preserveArrays`: Whether to preserve arrays (default: false)
### `pick` and `omit`
Create a new object with selected/omitted properties:
```typescript
pick(obj, keys, options);
omit(obj, keys, options);
```
**Options:**
- `preservePrototype`: Whether to preserve prototype chain (default: false)
- `includeNonEnumerable`: Whether to include non-enumerable properties (default: false)
## 📘 Network Utilities API
### `fetchWithCache`
Fetch data from an API with built-in caching support:
```typescript
fetchWithCache<T>(url: string, options?: CacheOptions): Promise<T>
```
**Options:**
- `cacheTTL`: Time-to-live for cache in milliseconds (default: 24 hours)
- `forceRefresh`: Whether to bypass cache and force a fresh API call (default: false)
- `cacheType`: Type of cache to use - 'memory' | 'lru' | 'persistent' (default: 'memory')
- `storage`: Storage type for persistent cache - 'localStorage' | 'indexedDB' (default: 'localStorage')
- `fetchOptions`: Additional fetch options to pass to the underlying fetch call
**Features:**
- Three cache strategies:
- Memory: Simple in-memory Map-based cache
- LRU (Least Recently Used): Efficient cache with automatic eviction of old entries
- Persistent: localStorage-based cache that persists across sessions
- Automatic cache invalidation based on TTL
- Type-safe responses with TypeScript generics
- Handles complex data types and serialization
- Automatic error handling and retries
## 🔧 Contributing
We welcome contributions of all sizes! Here's how you can help:
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
For major changes, please open an issue first to discuss what you'd like to change.
## 📄 License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
---
<div align="center">
<p>Made with 💚 by Kurama</p>
<p>⭐️ Star us on GitHub — it motivates us a lot!</p>
<p>
<a href="https://www.npmjs.com/package/mesh-fetcher">npm</a> •
<a href="https://github.com/vedas-dixit/mesh-fetch">GitHub</a> •
<a href="https://github.com/vedas-dixit/mesh-fetch/issues">Issues</a>
</p>
</div>
<div align=