/**
* Rate limiter for Todoist API
* Limit: 450 requests per 15 minutes
*/
export class RateLimiter {
private requests: number[] = [];
private readonly limit: number;
private readonly windowMs: number;
constructor(limit: number = 450, windowMs: number = 15 * 60 * 1000) {
this.limit = limit;
this.windowMs = windowMs;
}
/**
* Wait if necessary to stay within rate limit
*/
async throttle(): Promise<void> {
const now = Date.now();
// Remove requests outside the window
this.requests = this.requests.filter(t => now - t < this.windowMs);
if (this.requests.length >= this.limit) {
const oldestRequest = this.requests[0];
const waitTime = this.windowMs - (now - oldestRequest);
if (waitTime > 0) {
await this.sleep(waitTime);
}
}
this.requests.push(Date.now());
}
/**
* Get current usage stats
*/
getStats(): { used: number; limit: number; remaining: number } {
const now = Date.now();
this.requests = this.requests.filter(t => now - t < this.windowMs);
return {
used: this.requests.length,
limit: this.limit,
remaining: this.limit - this.requests.length,
};
}
private sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
}