UNPKG

n8n-nodes-sevdesk-v2

Version:

n8n community node for SevDesk API v2 integration with 24 production-ready workflow templates. Direct API access without external dependencies - simplified, secure, and optimized for German accounting automation (n8n 1.101.1 compatible).

99 lines (98 loc) 3.38 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.sevDeskRateLimiter = exports.RateLimiter = void 0; exports.withRateLimit = withRateLimit; class RateLimiter { constructor(config = {}) { this.requests = []; this.lastRequestTime = 0; this.config = { maxRequests: 100, windowMs: 60 * 1000, minDelay: 100, maxRetries: 3, baseRetryDelay: 1000, ...config, }; } async waitForSlot() { const now = Date.now(); this.cleanOldRequests(now); const timeSinceLastRequest = now - this.lastRequestTime; if (timeSinceLastRequest < this.config.minDelay) { const delayNeeded = this.config.minDelay - timeSinceLastRequest; await this.delay(delayNeeded); } if (this.requests.length >= this.config.maxRequests) { const oldestRequest = this.requests[0]; const waitTime = (oldestRequest.timestamp + this.config.windowMs) - Date.now(); if (waitTime > 0) { await this.delay(waitTime); this.cleanOldRequests(Date.now()); } } this.requests.push({ timestamp: Date.now(), retryCount: 0, }); this.lastRequestTime = Date.now(); } calculateRetryDelay(retryCount, retryAfter) { if (retryAfter) { return retryAfter * 1000; } const exponentialDelay = this.config.baseRetryDelay * Math.pow(2, retryCount); const jitter = Math.random() * 1000; return Math.min(exponentialDelay + jitter, 30000); } shouldRetry(retryCount) { return retryCount < this.config.maxRetries; } getStatus() { const now = Date.now(); this.cleanOldRequests(now); let nextAvailableSlot = now; const timeSinceLastRequest = now - this.lastRequestTime; if (timeSinceLastRequest < this.config.minDelay) { nextAvailableSlot = Math.max(nextAvailableSlot, this.lastRequestTime + this.config.minDelay); } if (this.requests.length >= this.config.maxRequests) { const oldestRequest = this.requests[0]; nextAvailableSlot = Math.max(nextAvailableSlot, oldestRequest.timestamp + this.config.windowMs); } return { requestsInWindow: this.requests.length, maxRequests: this.config.maxRequests, windowMs: this.config.windowMs, nextAvailableSlot, }; } reset() { this.requests = []; this.lastRequestTime = 0; } updateConfig(newConfig) { this.config = { ...this.config, ...newConfig }; } cleanOldRequests(now) { const cutoff = now - this.config.windowMs; this.requests = this.requests.filter(req => req.timestamp > cutoff); } delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } } exports.RateLimiter = RateLimiter; exports.sevDeskRateLimiter = new RateLimiter({ maxRequests: 100, windowMs: 60 * 1000, minDelay: 100, maxRetries: 3, baseRetryDelay: 1000, }); function withRateLimit(fn, rateLimiter = exports.sevDeskRateLimiter) { return (async (...args) => { await rateLimiter.waitForSlot(); return fn(...args); }); }