decortion
v1.0.0
Published
[](https://badge.fury.io/js/universal-decorators-complete) [](https://npmjs.org/package/universal-decor
Readme
🚀 Universal Decorators Complete - 17 Powerful Decorators
The complete JavaScript decorators library with 17 powerful decorators! 🌟
Write Python-style @decorators that work seamlessly across React, Vue, Angular, Node.js, Browser, TypeScript, and any JavaScript environment.
✨ All 17 Decorators
| # | Decorator | Description | Usage |
|---|-----------|-------------|-------|
| 1️⃣ | @super_cache | Fast/balanced/light caching | @super_cache('fast', 100) |
| 2️⃣ | @protect | Function protection (strict/normal/loose) | @protect('strict') |
| 3️⃣ | @logExecution | Log execution time and parameters | @logExecution({ timing: true }) |
| 4️⃣ | @repeat | Repeat function calls with delay | @repeat(3, 1000) |
| 5️⃣ | @loop_optimize | Optimize loops inside functions | @loop_optimize() |
| 6️⃣ | @search_optimize | Optimize search operations | @search_optimize({ algorithm: 'binary' }) |
| 7️⃣ | @var_guard | Variable protection and immutability | @var_guard({ immutable: true }) |
| 8️⃣ | @inheritFrom | Function inheritance from parent | @inheritFrom(parentFunction) |
| 9️⃣ | @immutable | Make objects immutable | @immutable({ deep: true }) |
| 🔟 | @time_limit | Stop function if exceeds time limit | @time_limit(5000) |
| 1️⃣1️⃣ | @debounce | Prevent multiple calls within period | @debounce(300) |
| 1️⃣2️⃣ | @throttle | Limit function call frequency | @throttle(1000) |
| 1️⃣3️⃣ | @async_retry | Retry async functions on failure | @async_retry({ attempts: 3 }) |
| 1️⃣4️⃣ | @validate | Validate parameters and return values | @validate({ params: [...] }) |
| 1️⃣5️⃣ | @rate_limit | Control function call rate | @rate_limit({ requests: 100, window: '1m' }) |
| 1️⃣6️⃣ | @metrics | Collect performance metrics | @metrics({ track: ['calls', 'duration'] }) |
| 1️⃣7️⃣ | @super_matrix | Combined decorator applying multiple decorators | @super_matrix({ cache: 'fast', protect: 'strict' }) |
📦 Installation
npm install universal-decorators-complete🚀 Quick Start
Individual Decorators
import {
super_cache, protect, logExecution, repeat,
debounce, throttle, async_retry, validate,
rate_limit, metrics
} from 'universal-decorators-complete';
class DataService {
// 1. Super fast caching
@super_cache('fast', 100)
expensiveCalculation(data) {
return data.reduce((sum, num) => sum + Math.sqrt(num), 0);
}
// 2. Function protection
@protect('strict')
sensitiveOperation(userData) {
return { ...userData, processed: true };
}
// 3. Execution logging
@logExecution({ timing: true, params: true })
importantProcess(input) {
return input * 2 + 10;
}
// 4. Auto-retry on failure
@repeat(3, 1000) // 3 attempts, 1s delay
unstableNetworkCall() {
if (Math.random() < 0.7) throw new Error('Network error');
return 'Success';
}
// 11. Debounce user input
@debounce(300)
handleUserInput(input) {
console.log('Processing:', input);
return `Processed: ${input}`;
}
// 12. Throttle frequent calls
@throttle(1000)
frequentApiCall(endpoint) {
return fetch(endpoint).then(r => r.json());
}
// 13. Async retry with exponential backoff
@async_retry({ attempts: 3, delay: 1000, exponentialBackoff: true })
async fetchFromAPI(url) {
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
}
// 14. Input validation
@validate({
params: [
{ type: 'string', required: true, min: 3 },
{ type: 'number', min: 0, max: 100 }
],
return: { type: 'object', required: true }
})
processUserData(name, age) {
return { name, age, processed: true };
}
// 15. Rate limiting
@rate_limit({
requests: 10,
window: '1m',
strategy: 'wait'
})
async limitedApiCall(data) {
return await fetch('/api/data', {
method: 'POST',
body: JSON.stringify(data)
}).then(r => r.json());
}
// 16. Performance metrics
@metrics({
track: ['calls', 'duration', 'errors'],
name: 'critical_operation'
})
criticalOperation(data) {
// Your critical business logic
return processImportantData(data);
}
}Super Matrix - All in One
import { super_matrix } from 'universal-decorators-complete';
@super_matrix({
cache: 'fast', // Enable fast caching
protect: 'strict', // Strict protection
log: { timing: true }, // Log execution time
repeat: 2, // Retry twice on failure
debounce: 300, // Debounce calls
timeLimit: 10000, // 10s timeout
immutable: true, // Make result immutable
asyncRetry: { attempts: 3 }, // Async retry
validate: { // Input validation
params: [{ type: 'object', required: true }]
},
rateLimit: { // Rate limiting
requests: 50,
window: '1m'
},
metrics: true // Performance metrics
})
async function ultimateFunction(data) {
// Your complex logic here with all protections
return await processComplexData(data);
}🎨 Detailed Decorator Guide
1️⃣ Super Cache - Lightning Fast Caching
// Cache types: 'light' (32), 'balanced' (128), 'fast' (256+)
@super_cache('fast', 200)
function fibonacci(n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
// Check cache statistics
console.log(fibonacci.cache_info());
// { hits: 45, misses: 31, ratio: 59.2, currsize: 31, maxsize: 200 }
// Clear cache
fibonacci.cache_clear();2️⃣ Protect - Function & Data Protection
// Protection levels: 'loose', 'normal', 'strict'
@protect('strict')
function safeFunction(userData) {
// Input objects are automatically deep cloned
// Output objects are frozen in strict mode
// Errors are caught and handled gracefully
return { ...userData, processed: true };
}3️⃣ Log Execution - Smart Logging
@logExecution({
timing: true, // Log execution time
params: true, // Log input parameters
result: false, // Don't log result (sensitive data)
level: 'info' // Log level
})
function processPayment(amount, cardDetails) {
return { success: true, transactionId: 'tx_123' };
}
// Output:
// [INFO] [processPayment] Called with: [100, {...}]
// [INFO] [processPayment] Completed in 45.23ms4️⃣ Repeat - Automatic Retry
@repeat(3, 1000) // 3 attempts, 1000ms delay between attempts
function unstableOperation() {
if (Math.random() < 0.6) {
throw new Error('Random failure');
}
return 'Success!';
}5️⃣ Loop Optimize - Performance Optimization
@loop_optimize() // Uses requestAnimationFrame in browser, setImmediate in Node.js
function heavyLoopOperation(data) {
return data.map(item => {
// Heavy processing that benefits from optimization
let result = 0;
for (let i = 0; i < 10000; i++) {
result += Math.sqrt(item + i);
}
return result;
});
}6️⃣ Search Optimize - Smart Search Algorithms
@search_optimize({
algorithm: 'binary', // 'binary', 'linear', 'hash'
cacheResults: true, // Cache search results
indexKeys: ['id', 'name'] // Index these keys for faster lookup
})
function searchUsers(users, criteria) {
return users.filter(user =>
user.name.toLowerCase().includes(criteria.toLowerCase())
);
}7️⃣ Var Guard - Variable Protection
@var_guard({
immutable: true, // Prevent variable modification
deepFreeze: true, // Deep freeze objects
validateTypes: true // Type validation
})
function processSecureData(data) {
this.internalState = 'modified'; // Will be warned/prevented
return { result: data.value * 2 };
}8️⃣ Inherit From - Function Inheritance
function baseCalculation(x, y) {
return { sum: x + y };
}
@inheritFrom(baseCalculation, {
mergeResults: true, // Merge parent and child results
callParentFirst: true, // Call parent before child
inheritProperties: true // Inherit parent properties
})
function enhancedCalculation(x, y) {
return { product: x * y, enhanced: true };
}
// Result: { sum: 15, product: 35, enhanced: true }
console.log(enhancedCalculation(5, 7));9️⃣ Immutable - Data Immutability
@immutable({
deep: true, // Deep freeze all nested objects
strict: true, // Strict immutability mode
allowNew: false // Don't allow new properties
})
function createConfiguration(options) {
return {
server: { port: 3000, host: 'localhost' },
database: { url: 'mongodb://localhost' },
...options
};
}
// Returned object is completely immutable
const config = createConfiguration({ debug: true });
// config.server.port = 8080; // This will fail🔟 Time Limit - Execution Timeout
@time_limit(5000) // 5 second timeout
async function potentiallySlowOperation(data) {
// This will be cancelled if it takes longer than 5 seconds
return await processLargeDataset(data);
}
// Usage
try {
const result = await potentiallySlowOperation(hugeDataset);
} catch (error) {
console.error('Operation timed out:', error.message);
}1️⃣1️⃣ Debounce - Rate Limiting
@debounce(300) // Wait 300ms after last call
function handleUserInput(searchTerm) {
console.log('Searching for:', searchTerm);
return performSearch(searchTerm);
}
// Multiple rapid calls will be debounced
handleUserInput('a'); // Cancelled
handleUserInput('ap'); // Cancelled
handleUserInput('app'); // Cancelled
handleUserInput('apple'); // Executed after 300ms1️⃣2️⃣ Throttle - Call Rate Control
@throttle(1000) // Maximum once per second
function trackUserAction(action) {
console.log('Tracking:', action);
return analytics.track(action);
}
// Rapid calls will be throttled
trackUserAction('click'); // Executed immediately
trackUserAction('click'); // Ignored (too soon)
trackUserAction('click'); // Ignored (too soon)
// ... 1 second later ...
trackUserAction('click'); // Executed1️⃣3️⃣ Async Retry - Advanced Retry Logic
@async_retry({
attempts: 5, // Try 5 times
delay: 1000, // Start with 1s delay
exponentialBackoff: true, // Double delay each time
retryOn: [NetworkError, TimeoutError] // Only retry these errors
})
async function fetchCriticalData(url) {
const response = await fetch(url);
if (!response.ok) {
throw new NetworkError(`HTTP ${response.status}`);
}
return response.json();
}
// Will retry: 1s, 2s, 4s, 8s delays between attempts1️⃣4️⃣ Validate - Input/Output Validation
@validate({
params: [
{
type: 'string',
required: true,
min: 3,
max: 50,
pattern: /^[a-zA-Z\s]+$/,
message: 'Name must be 3-50 alphabetic characters'
},
{
type: 'number',
required: true,
min: 0,
max: 120,
message: 'Age must be between 0 and 120'
},
{
type: 'object',
required: false,
validate: (obj) => obj.hasOwnProperty('email'),
message: 'Object must have email property'
}
],
return: {
type: 'object',
required: true,
validate: (result) => result.hasOwnProperty('id'),
message: 'Result must contain an ID'
},
throwOnError: true,
logErrors: true
})
function createUser(name, age, options = {}) {
return {
id: Date.now(),
name,
age,
email: options.email || `${name.toLowerCase()}@example.com`,
created: new Date()
};
}
// Usage
try {
const user = createUser('John Doe', 25, { email: '[email protected]' });
console.log(user); // Valid user object
} catch (error) {
console.error('Validation failed:', error.message);
}1️⃣5️⃣ Rate Limit - Call Rate Control
@rate_limit({
requests: 100, // Maximum 100 requests
window: '1m', // Per minute ('1s', '1m', '1h', '1d')
per: (userId) => userId, // Rate limit per user ID
strategy: 'wait', // 'wait', 'reject', or 'cache'
message: 'Too many requests, please slow down'
})
async function apiCall(userId, data) {
return await fetch('/api/process', {
method: 'POST',
headers: { 'user-id': userId },
body: JSON.stringify(data)
}).then(r => r.json());
}
// Different strategies:
// 'reject' - Throw error when limit exceeded
// 'wait' - Wait until rate limit window resets
// 'cache' - Return cached result if available
// Per-user rate limiting
@rate_limit({
requests: 10,
window: '1m',
per: (req) => req.ip, // Rate limit per IP address
strategy: 'reject'
})
function handleRequest(req) {
return processRequest(req);
}1️⃣6️⃣ Metrics - Performance Monitoring
@metrics({
track: ['calls', 'duration', 'errors', 'success'], // What to track
name: 'payment_processor', // Custom metric name
labels: { service: 'billing', version: '2.1' }, // Custom labels
type: 'histogram', // Metric type
buckets: [0.1, 0.5, 1, 2.5, 5, 10] // Histogram buckets
})
async function processPayment(amount, paymentMethod) {
// Your payment processing logic
const result = await chargePayment(amount, paymentMethod);
if (!result.success) {
throw new Error('Payment failed');
}
return result;
}
// Access metrics
console.log(processPayment.getMetrics());
/*
{
counters: {
'payment_processor_calls_total{service="billing",version="2.1"}': 150,
'payment_processor_errors_total{service="billing",version="2.1",error="PaymentError"}': 3
},
gauges: {
'payment_processor_success{service="billing",version="2.1"}': 1
},
histograms: {
'payment_processor_duration_seconds{service="billing",version="2.1"}': [0.1, 0.2, 0.15, ...]
}
}
*/
// Clear metrics
processPayment.clearMetrics();1️⃣7️⃣ Super Matrix - Ultimate Decorator
// Combine all decorators with intelligent configuration
@super_matrix({
// Caching
cache: {
type: 'fast',
maxsize: 500
},
// Protection & Security
protect: 'strict',
varGuard: {
immutable: true,
deepFreeze: true
},
// Validation
validate: {
params: [
{ type: 'object', required: true },
{ type: 'string', required: false }
],
return: { type: 'object', required: true },
throwOnError: true
},
// Rate Limiting
rateLimit: {
requests: 50,
window: '1m',
strategy: 'wait'
},
// Retry & Resilience
timeLimit: 30000,
asyncRetry: {
attempts: 3,
delay: 1000,
exponentialBackoff: true
},
repeat: 2,
// Performance & Optimization
debounce: 500,
throttle: 2000,
loop: true,
search: {
algorithm: 'binary',
cacheResults: true
},
// Monitoring & Logging
log: {
timing: true,
params: false, // Don't log sensitive data
result: false,
level: 'info'
},
metrics: {
track: ['calls', 'duration', 'errors'],
name: 'ultimate_function',
labels: { category: 'business_critical' }
},
// Data Integrity
immutable: {
deep: true,
strict: true
}
})
async function ultimateBusinessFunction(requestData, options) {
// This function now has ALL 17 decorators applied intelligently:
// - Cached for performance
// - Protected from tampering
// - Validated inputs/outputs
// - Rate limited
// - Auto-retry on failure
// - Timeout protection
// - Debounced/throttled
// - Performance monitored
// - Fully logged
// - Immutable results
// - Variable protection
// - Loop optimization
// - Search optimization
return await processBusinessLogic(requestData, options);
}🌟 Framework Examples
⚛️ React with Hooks
import React, { useState } from 'react';
import {
useCachedFunction,
useDebouncedFunction,
super_cache,
debounce,
metrics
} from 'universal-decorators-complete';
function SearchComponent() {
const [query, setQuery] = useState('');
const [results, setResults] = useState([]);
// Cached search function
const searchData = useCachedFunction(
(searchTerm) => performExpensiveSearch(searchTerm),
'fast',
[]
);
// Debounced search handler
const debouncedSearch = useDebouncedFunction(
(term) => setResults(searchData(term)),
300,
[searchData]
);
return (
<div>
<input
value={query}
onChange={(e) => {
setQuery(e.target.value);
debouncedSearch(e.target.value);
}}
placeholder="Search..."
/>
<div>
{results.map(item => (
<div key={item.id}>{item.title}</div>
))}
</div>
</div>
);
}
// Class component with decorators
class DataProcessor extends React.Component {
@super_cache('balanced', 50)
@metrics({ track: ['calls', 'duration'] })
processData(data) {
return data.map(item => ({
...item,
processed: true,
timestamp: Date.now()
}));
}
@debounce(500)
@validate({
params: [{ type: 'string', required: true, min: 1 }]
})
handleSearch(query) {
const results = this.processData(this.props.data);
return results.filter(item =>
item.title.toLowerCase().includes(query.toLowerCase())
);
}
render() {
return (
<div>
<SearchInput onSearch={this.handleSearch} />
<ResultsList data={this.state.results} />
</div>
);
}
}🟢 Vue.js Integration
<template>
<div>
<input v-model="searchTerm" @input="handleSearch" />
<div v-for="result in results" :key="result.id">
{{ result.title }}
</div>
</div>
</template>
<script>
import {
super_cache,
debounce,
validate,
rate_limit
} from 'universal-decorators-complete';
export default {
name: 'SearchComponent',
data() {
return {
searchTerm: '',
results: []
};
},
methods: {
// Apply decorators to Vue methods
...this.$decorate({
@super_cache('fast', 100)
@validate({
params: [{ type: 'string', required: true }],
return: { type: 'array', required: true }
})
async fetchSearchResults(query) {
const response = await fetch(`/api/search?q=${query}`);
return response.json();
},
@debounce(300)
@rate_limit({ requests: 10, window: '1m' })
async handleSearch() {
if (this.searchTerm.length > 2) {
this.results = await this.fetchSearchResults(this.searchTerm);
}
}
})
}
};
</script>🅰️ Angular Service
import { Injectable } from '@angular/core';
import {
super_cache,
async_retry,
rate_limit,
metrics,
validate
} from 'universal-decorators-complete';
@Injectable({
providedIn: 'root'
})
export class ApiService {
@super_cache('balanced', 200)
@async_retry({
attempts: 3,
delay: 1000,
exponentialBackoff: true
})
@rate_limit({
requests: 50,
window: '1m',
strategy: 'wait'
})
@metrics({
track: ['calls', 'duration', 'errors'],
name: 'api_call'
})
@validate({
params: [{ type: 'string', required: true }],
return: { type: 'object', required: true }
})
async fetchUserData(userId: string): Promise<any> {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
}
@debounce(500)
@validate({
params: [
{ type: 'object', required: true },
{ type: 'string', required: false }
]
})
async updateUser(userData: any, reason?: string): Promise<any> {
return fetch('/api/users', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ...userData, updateReason: reason })
}).then(r => r.json());
}
}🟦 Node.js & Express
const express = require('express');
const {
super_cache,
rate_limit,
validate,
logExecution,
async_retry,
protect,
metrics
} = require('universal-decorators-complete');
const app = express();
class UserController {
@super_cache('fast', 1000)
@rate_limit({
requests: 100,
window: '1m',
per: (req) => req.ip
})
@logExecution({
timing: true,
params: false,
level: 'info'
})
@metrics({
track: ['calls', 'duration'],
labels: { endpoint: 'get_users' }
})
async getUsers(req, res) {
const users = await this.fetchUsersFromDB();
res.json(users);
}
@validate({
params: [
{ /* req validation */ },
{ /* res validation */ },
{
type: 'object',
validate: (body) => body.name && body.email,
message: 'Name and email are required'
}
]
})
@async_retry({ attempts: 3, delay: 500 })
@protect('normal')
@logExecution({ timing: true, level: 'info' })
async createUser(req, res, userData) {
try {
const newUser = await this.saveUserToDB(userData);
res.status(201).json(newUser);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
@rate_limit({
requests: 10,
window: '1h',
per: (req) => req.user?.id
})
async deleteUser(req, res) {
const userId = req.params.id;
await this.removeUserFromDB(userId);
res.status(204).send();
}
}
const userController = new UserController();
// Apply routes
app.get('/users', userController.getUsers.bind(userController));
app.post('/users', userController.createUser.bind(userController));
app.delete('/users/:id', userController.deleteUser.bind(userController));
app.listen(3000, () => {
console.log('Server running on port 3000');
});🌐 Browser/Vanilla JavaScript
<!DOCTYPE html>
<html>
<head>
<title>Universal Decorators Demo</title>
<script src="https://unpkg.com/[email protected]/dist/index.umd.js"></script>
</head>
<body>
<div>
<input id="search" placeholder="Search..." />
<div id="results"></div>
</div>
<script>
const {
super_cache,
debounce,
throttle,
validate,
rate_limit
} = window.decorators;
// Search functionality with decorators
const searchAPI = super_cache('fast', 50)(
validate({
params: [{ type: 'string', required: true, min: 2 }],
return: { type: 'array', required: true }
})(
async function(query) {
const response = await fetch(`/api/search?q=${encodeURIComponent(query)}`);
return response.json();
}
)
);
const debouncedSearch = debounce(300)(async function(query) {
try {
const results = await searchAPI(query);
displayResults(results);
} catch (error) {
console.error('Search failed:', error);
}
});
const rateLimitedTracker = rate_limit({
requests: 20,
window: '1m',
strategy: 'throttle'
})(function(event) {
console.log('User action:', event);
// Track user behavior
});
// Event listeners
document.getElementById('search').addEventListener('input', (e) => {
debouncedSearch(e.target.value);
rateLimitedTracker('search_input');
});
function displayResults(results) {
const container = document.getElementById('results');
container.innerHTML = results
.map(item => `<div>${item.title}</div>`)
.join('');
}
</script>
</body>
</html>🚀 Advanced Usage Patterns
Decorator Composition
// Create reusable decorator combinations
const apiDecorator = (name) => super_matrix({
cache: 'balanced',
asyncRetry: { attempts: 3, exponentialBackoff: true },
rateLimit: { requests: 100, window: '1m' },
validate: { throwOnError: true },
metrics: { name, track: ['calls', 'duration', 'errors'] },
log: { timing: true, level: 'info' }
});
const databaseDecorator = super_matrix({
cache: 'fast',
protect: 'strict',
timeLimit: 30000,
asyncRetry: { attempts: 5, delay: 2000 },
metrics: { track: ['calls', 'duration', 'errors'] }
});
// Apply to functions
@apiDecorator('user_service')
async function fetchUserProfile(userId) {
return await api.get(`/users/${userId}`);
}
@databaseDecorator
async function saveUserData(userData) {
return await database.users.create(userData);
}Performance Monitoring
import { performanceMonitor } from 'universal-decorators-complete';
// Start profiling
performanceMonitor.startProfiling();
// Your decorated functions run...
// Get comprehensive performance insights
const insights = performanceMonitor.getPerformanceInsights();
console.log('Slowest Functions:', insights.slowestFunctions);
console.log('Most Cached:', insights.mostCachedFunctions);
console.log('Most Retried:', insights.mostRetriedFunctions);
// Export metrics for external monitoring
const metricsData = performanceMonitor.exportMetrics();
// Send to your monitoring serviceError Handling & Debugging
import {
DecoratorError,
ValidationError,
RateLimitError,
TimeoutError
} from 'universal-decorators-complete';
try {
await decoratedFunction(data);
} catch (error) {
if (error instanceof ValidationError) {
console.error('Validation failed:', error.fieldName, error.message);
} else if (error instanceof RateLimitError) {
console.error('Rate limited. Retry after:', error.retryAfter, 'seconds');
} else if (error instanceof TimeoutError) {
console.error('Function timed out after:', error.timeLimit, 'ms');
} else if (error instanceof DecoratorError) {
console.error('Decorator error in:', error.decoratorName);
}
}📊 Configuration & Customization
import { configure, getConfig, resetConfig } from 'universal-decorators-complete';
// Global configuration
configure({
defaultCacheType: 'fast',
defaultCacheSize: 256,
defaultProtectionLevel: 'strict',
enablePerformanceMonitoring: true,
enableDebugMode: true,
logLevel: 'info',
// Environment-specific settings
browser: {
useWebWorkers: true,
maxWorkers: 4
},
node: {
useWorkerThreads: true,
maxThreads: 8
},
// Framework integration
react: {
enableHooks: true,
enableDevtools: true
}
});
// Get current configuration
const config = getConfig();
console.log('Current config:', config);
// Reset to defaults
resetConfig();🧪 Testing
import { testUtils } from 'universal-decorators-complete';
describe('Decorated Functions', () => {
beforeEach(() => {
testUtils.resetAll();
});
test('should cache function results', () => {
const mockFn = jest.fn().mockReturnValue('result');
const cachedFn = super_cache()(mockFn);
// First call
expect(cachedFn()).toBe('result');
// Second call (should use cache)
expect(cachedFn()).toBe('result');
expect(mockFn).toHaveBeenCalledTimes(1);
expect(cachedFn.cache_info().hits).toBe(1);
});
test('should validate inputs', () => {
const validatedFn = validate({
params: [{ type: 'string', required: true }]
})((str) => str.toUpperCase());
expect(() => validatedFn()).toThrow(ValidationError);
expect(() => validatedFn(123)).toThrow(ValidationError);
expect(validatedFn('hello')).toBe('HELLO');
});
test('should respect rate limits', async () => {
const rateLimitedFn = rate_limit({
requests: 2,
window: '1s',
strategy: 'reject'
})(() => 'success');
expect(await rateLimitedFn()).toBe('success');
expect(await rateLimitedFn()).toBe('success');
await expect(rateLimitedFn()).rejects.toThrow(RateLimitError);
});
});📈 Bundle Size & Performance
- Main bundle: ~32KB gzipped
- Individual decorators: ~2-4KB each
- Zero dependencies
- Tree-shakeable: Import only what you need
- TypeScript: Full type safety included
- Universal: Works in all JavaScript environments
🤝 Contributing
We welcome contributions! Please read our Contributing Guide for details.
📄 License
MIT License - see LICENSE file for details.
🌟 Star History
Made with ❤️ for the JavaScript community
