@oakshade/squirrel
v1.0.3
Published
Intelligent API caching with TypeScript - 100x faster responses, 99% fewer API calls
Maintainers
Readme
@oakshade/squirrel 🐿️
Intelligent API caching with TypeScript - 100x faster responses, 99% fewer API calls
Features
- 100x Faster - Cached responses in milliseconds vs seconds
- 99% Fewer API Calls - Request deduplication for concurrent users (100 users → 1 API call)
- Error Resilient - Stale cache fallback when APIs fail
- Full TypeScript - Complete type safety
- Automatic - One-line API calls with smart caching
- Production Ready - Memory management, auto-cleanup, statistics
📦 Installation
npm install @oakshade/squirrelor
yarn add @oakshade/squirrel🚀 Quick Start
import { Squirrel } from '@oakshade/squirrel';
const cache = new Squirrel();🧪 Demo 1: Basic API Caching
Cache an API response for 5 minutes and instantly serve repeated requests.
import { Squirrel } from '@oakshade/squirrel';
// Create cache
const cache = new Squirrel();
// DEMO 1: Basic Caching
async function getWeather() {
return cache.fetch(
`https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41¤t_weather=true`,
{
ttl: 300, // 5 minutes
}
);
}
// User checks for weather
const start1 = Date.now();
const weather1 = await getWeather();
const time1 = Date.now() - start1;
// Same user checks again 1 second later
const start2 = Date.now();
const weather2 = await getWeather();
const time2 = Date.now() - start2;
console.log(`First check: ${time1}ms (API call)`);
console.log(
`Second check: ${time2}ms (Cached) ${Math.round(time1 / time2)}x faster!`
);
console.log(`${weather1.current_weather.temperature}°C`);
console.log(`${weather2.current_weather.temperature}°C`);✅ Result: Second request is served from cache in milliseconds.
🧨 Demo 2: Flash Sale / High Concurrency Protection
Prevent API overload when hundreds of users request the same data simultaneously.
import { Squirrel } from '@oakshade/squirrel';
// Create cache
const cache = new Squirrel();
async function getProduct(productId) {
const url = `https://jsonplaceholder.typicode.com/posts/${productId}`;
return cache.fetch(url, {
ttl: 60,
});
}
// Simulate 100 users hitting "Refresh" at same time
const startTime = Date.now();
const userRequests = Array(100)
.fill(null)
.map((_, i) => getProduct('1').then(() => ({ user: i + 1 })));
await Promise.all(userRequests);
const totalTime = Date.now() - startTime;
console.log(`Flash sale starts! ${userRequests.length} users check product #1`);
console.log(`Total time: ${totalTime}ms`);
console.log(`API calls made: 1 (not ${userRequests.length})`);
console.log(
`Each user got response in ${Math.round(totalTime / userRequests.length)}ms`
);✅ Result: Only one API call, regardless of traffic spike.
📴 Demo 3: Offline Support with Stale Cache
Serve cached data even when the network fails.
import { Squirrel } from '@oakshade/squirrel';
const newsCache = new Squirrel();
async function loadNews() {
const url = 'https://jsonplaceholder.typicode.com/posts/1';
return newsCache.fetch(url, {
ttl: 300,
onCacheMiss: () => console.log(`Fetching fresh news...`),
onCacheHit: () => console.log('Showing cached news'),
});
}
// User opens app (online)
const news = await loadNews();
// User goes offline and opens app again
const offlineFetcher = async () => {
throw new Error('No internet connection');
};
const offlineNews = await newsCache.fetch(
'https://jsonplaceholder.typicode.com/posts/1',
{
fetcher: offlineFetcher,
staleOnError: true,
}
);✅ Result: Your app keeps working even without internet.
📊 Demo 4: Dashboard with Batch Fetching
Load multiple widgets efficiently with one optimized cache layer.
import { Squirrel } from '@oakshade/squirrel';
async function demoDashboard() {
const dashboardCache = new Squirrel();
const widgets = [
{ id: 'users', url: 'https://jsonplaceholder.typicode.com/users', ttl: 60 },
{ id: 'posts', url: 'https://jsonplaceholder.typicode.com/posts', ttl: 30 },
{
id: 'comments',
url: 'https://jsonplaceholder.typicode.com/comments',
ttl: 30,
},
{
id: 'albums',
url: 'https://jsonplaceholder.typicode.com/albums',
ttl: 300,
},
{
id: 'photos',
url: 'https://jsonplaceholder.typicode.com/photos',
ttl: 300,
},
];
// First load - all widgets fresh
const firstLoadStart = Date.now();
const firstResults = await dashboardCache.batchFetch(
widgets.map((w) => ({
url: w.url,
options: { ttl: w.ttl, cacheKey: `widget:${w.id}` },
}))
);
const firstLoadTime = Date.now() - firstLoadStart;
// User refreshes dashboard
const refreshStart = Date.now();
await dashboardCache.batchFetch(
widgets.map((w) => ({
url: w.url,
options: { cacheKey: `widget:${w.id}` },
}))
);
const refreshTime = Date.now() - refreshStart;
return dashboardCache;
}
demoDashboard();✅ Result: Instant dashboard refresh with zero unnecessary API calls.
🧠 Why Squirrel?
| Problem | Solution | | --------------- | ---------------------- | | API rate limits | Request deduplication | | Slow dashboards | Batch fetch + cache | | Offline users | Stale-on-error support | | Traffic spikes | Single-flight requests |
🛠️ Ideal Use Cases
- Admin dashboards
- SaaS platforms
- Flash sales
- News & media apps
- Mobile & offline-first apps
- High-traffic APIs
📄 License
MIT License © Oakshade
🌱 Contributing
Pull requests are welcome. If you find a bug or have a feature request, please open an issue.
Built for speed. Designed for scale. 🚀 🐿️ Cache smarter with Squirrel.
