@se-studio/contentful-rest-api 1.0.19 → 1.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -212,6 +212,27 @@ function buildQueryString(query) {
212
212
  });
213
213
  return params.toString();
214
214
  }
215
+ function sleep(ms) {
216
+ return new Promise((resolve) => setTimeout(resolve, ms));
217
+ }
218
+ function calculateRetryDelay(attempt, retryAfterSeconds) {
219
+ let baseDelay;
220
+ if (retryAfterSeconds !== void 0 && retryAfterSeconds > 0) {
221
+ baseDelay = retryAfterSeconds * 1e3;
222
+ } else {
223
+ baseDelay = 1e3 * 2 ** attempt;
224
+ }
225
+ const jitter = Math.random() * baseDelay;
226
+ return Math.min(baseDelay + jitter, 15e3);
227
+ }
228
+ function parseRetryAfter(response) {
229
+ const retryAfterHeader = response.headers.get("X-Contentful-RateLimit-Reset") || response.headers.get("Retry-After");
230
+ if (retryAfterHeader) {
231
+ const parsed = Number.parseInt(retryAfterHeader, 10);
232
+ return Number.isNaN(parsed) ? void 0 : parsed;
233
+ }
234
+ return void 0;
235
+ }
215
236
  async function parseErrorResponse(response) {
216
237
  const statusCode = response.status;
217
238
  let errorData;
@@ -250,7 +271,7 @@ var ContentfulFetchClient = class {
250
271
  this.accessToken = config.accessToken;
251
272
  }
252
273
  /**
253
- * Fetches entries from Contentful
274
+ * Fetches entries from Contentful with automatic retry on rate limit errors
254
275
  */
255
276
  async getEntries(query, options) {
256
277
  const queryString = buildQueryString(query);
@@ -264,11 +285,26 @@ var ContentfulFetchClient = class {
264
285
  if (options?.next) {
265
286
  fetchOptions.next = options.next;
266
287
  }
267
- const response = await fetch(url, fetchOptions);
268
- if (!response.ok) {
288
+ const maxRetries = 3;
289
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
290
+ const response = await fetch(url, fetchOptions);
291
+ if (response.ok) {
292
+ return response.json();
293
+ }
294
+ if (response.status === 429 && attempt < maxRetries) {
295
+ const retryAfter = parseRetryAfter(response);
296
+ const delay3 = calculateRetryDelay(attempt, retryAfter);
297
+ if (typeof process !== "undefined" && process.env?.NODE_ENV !== "production") {
298
+ console.warn(
299
+ `[Contentful] Rate limited, retrying in ${delay3}ms (attempt ${attempt + 1}/${maxRetries})`
300
+ );
301
+ }
302
+ await sleep(delay3);
303
+ continue;
304
+ }
269
305
  throw await parseErrorResponse(response);
270
306
  }
271
- return response.json();
307
+ throw new ContentfulError("Unexpected error in retry loop", 500);
272
308
  }
273
309
  };
274
310
  function createContentfulClient(config) {
@@ -634,7 +670,7 @@ var DEFAULT_RETRY_CONFIG = {
634
670
  // 30 seconds
635
671
  backoffMultiplier: 2
636
672
  };
637
- function sleep(ms) {
673
+ function sleep2(ms) {
638
674
  return new Promise((resolve) => setTimeout(resolve, ms));
639
675
  }
640
676
  function calculateBackoffDelay(attempt, config, retryAfter) {
@@ -678,7 +714,7 @@ async function withRetry(fn, config) {
678
714
  error
679
715
  );
680
716
  }
681
- await sleep(delay3);
717
+ await sleep2(delay3);
682
718
  }
683
719
  }
684
720
  throw lastError;
@@ -720,7 +756,7 @@ var RateLimiter = class {
720
756
  async consume() {
721
757
  while (!this.tryConsume()) {
722
758
  const waitTime = 1 / this.refillRate * 1e3;
723
- await sleep(waitTime);
759
+ await sleep2(waitTime);
724
760
  }
725
761
  }
726
762
  /**