@profplum700/etsy-v3-api-client 2.5.2 → 2.5.4

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.cjs CHANGED
@@ -677,6 +677,11 @@ class FileTokenStorage {
677
677
  }
678
678
  }
679
679
 
680
+ const ETSY_RATE_LIMITS = {
681
+ MAX_REQUESTS_PER_DAY: 5000,
682
+ MAX_REQUESTS_PER_SECOND: 5,
683
+ MIN_REQUEST_INTERVAL: 200,
684
+ };
680
685
  class EtsyRateLimiter {
681
686
  constructor(config) {
682
687
  this.requestCount = 0;
@@ -685,9 +690,9 @@ class EtsyRateLimiter {
685
690
  this.isHeaderBasedLimiting = false;
686
691
  this.currentRetryCount = 0;
687
692
  this.config = {
688
- maxRequestsPerDay: 10000,
689
- maxRequestsPerSecond: 10,
690
- minRequestInterval: 100,
693
+ maxRequestsPerDay: ETSY_RATE_LIMITS.MAX_REQUESTS_PER_DAY,
694
+ maxRequestsPerSecond: ETSY_RATE_LIMITS.MAX_REQUESTS_PER_SECOND,
695
+ minRequestInterval: ETSY_RATE_LIMITS.MIN_REQUEST_INTERVAL,
691
696
  maxRetries: 3,
692
697
  baseDelayMs: 1000,
693
698
  maxDelayMs: 30000,
@@ -742,7 +747,7 @@ class EtsyRateLimiter {
742
747
  if (value === null)
743
748
  return undefined;
744
749
  const num = parseInt(value, 10);
745
- return isNaN(num) ? undefined : num;
750
+ return Number.isNaN(num) ? undefined : num;
746
751
  };
747
752
  return {
748
753
  limitPerSecond: parseNumber(getHeader('x-limit-per-second')),
@@ -1083,7 +1088,7 @@ class FieldValidator {
1083
1088
  const value = data[this.field];
1084
1089
  if (value === undefined || value === null)
1085
1090
  return null;
1086
- if (typeof value !== 'number' || isNaN(value)) {
1091
+ if (typeof value !== 'number' || Number.isNaN(value)) {
1087
1092
  return {
1088
1093
  field: this.field,
1089
1094
  message: options.message || `${this.field} must be a number`,
@@ -1292,9 +1297,14 @@ function combineValidators(...validators) {
1292
1297
 
1293
1298
  class DefaultLogger {
1294
1299
  debug(message, ...args) {
1295
- const isDevelopment = isNode$1
1296
- ? process.env.NODE_ENV === 'development'
1297
- : window.location?.hostname === 'localhost' || window.location?.hostname === '127.0.0.1';
1300
+ let isDevelopment;
1301
+ if (isNode$1) {
1302
+ isDevelopment = process.env.NODE_ENV === 'development';
1303
+ }
1304
+ else {
1305
+ const host = window.location?.hostname;
1306
+ isDevelopment = host === 'localhost' || host === '127.0.0.1';
1307
+ }
1298
1308
  if (isDevelopment) {
1299
1309
  console.log(`[DEBUG] ${message}`, ...args);
1300
1310
  }
@@ -1343,9 +1353,9 @@ class EtsyClient {
1343
1353
  this.sharedSecret = config.sharedSecret;
1344
1354
  if (config.rateLimiting?.enabled !== false) {
1345
1355
  this.rateLimiter = new EtsyRateLimiter({
1346
- maxRequestsPerDay: config.rateLimiting?.maxRequestsPerDay || 10000,
1347
- maxRequestsPerSecond: config.rateLimiting?.maxRequestsPerSecond || 10,
1348
- minRequestInterval: config.rateLimiting?.minRequestInterval ?? 100,
1356
+ maxRequestsPerDay: config.rateLimiting?.maxRequestsPerDay || ETSY_RATE_LIMITS.MAX_REQUESTS_PER_DAY,
1357
+ maxRequestsPerSecond: config.rateLimiting?.maxRequestsPerSecond || ETSY_RATE_LIMITS.MAX_REQUESTS_PER_SECOND,
1358
+ minRequestInterval: config.rateLimiting?.minRequestInterval ?? ETSY_RATE_LIMITS.MIN_REQUEST_INTERVAL,
1349
1359
  maxRetries: config.rateLimiting?.maxRetries,
1350
1360
  baseDelayMs: config.rateLimiting?.baseDelayMs,
1351
1361
  maxDelayMs: config.rateLimiting?.maxDelayMs,
@@ -1376,7 +1386,12 @@ class EtsyClient {
1376
1386
  if (useCache && this.cache && requestOptions.method === 'GET') {
1377
1387
  const cached = await this.cache.get(cacheKey);
1378
1388
  if (cached) {
1379
- return JSON.parse(cached);
1389
+ try {
1390
+ return JSON.parse(cached);
1391
+ }
1392
+ catch {
1393
+ await this.cache.delete(cacheKey);
1394
+ }
1380
1395
  }
1381
1396
  }
1382
1397
  await this.rateLimiter.waitForRateLimit();
@@ -1441,11 +1456,7 @@ class EtsyClient {
1441
1456
  if (value === undefined || value === null)
1442
1457
  continue;
1443
1458
  if (Array.isArray(value)) {
1444
- for (const item of value) {
1445
- if (item === undefined || item === null)
1446
- continue;
1447
- body.append(key, String(item));
1448
- }
1459
+ body.append(key, value.filter(item => item !== undefined && item !== null).map(String).join(','));
1449
1460
  }
1450
1461
  else {
1451
1462
  body.append(key, String(value));
@@ -2610,9 +2621,9 @@ class GlobalRequestQueue {
2610
2621
  this.requestCount = 0;
2611
2622
  this.dailyReset = new Date();
2612
2623
  this.lastRequestTime = 0;
2613
- this.maxRequestsPerDay = 10000;
2614
- this.maxRequestsPerSecond = 10;
2615
- this.minRequestInterval = 100;
2624
+ this.maxRequestsPerDay = ETSY_RATE_LIMITS.MAX_REQUESTS_PER_DAY;
2625
+ this.maxRequestsPerSecond = ETSY_RATE_LIMITS.MAX_REQUESTS_PER_SECOND;
2626
+ this.minRequestInterval = ETSY_RATE_LIMITS.MIN_REQUEST_INTERVAL;
2616
2627
  this.setNextDailyReset();
2617
2628
  }
2618
2629
  static getInstance() {
@@ -2697,11 +2708,12 @@ class GlobalRequestQueue {
2697
2708
  try {
2698
2709
  let result;
2699
2710
  if (item.timeout) {
2700
- const remainingTimeout = item.timeout - elapsed;
2711
+ const timeout = item.timeout;
2712
+ const remainingTimeout = timeout - elapsed;
2701
2713
  let timeoutId;
2702
2714
  const timeoutPromise = new Promise((_, reject) => {
2703
2715
  timeoutId = setTimeout(() => {
2704
- reject(new Error(`Request timeout after ${item.timeout}ms (exceeded during execution)`));
2716
+ reject(new Error(`Request timeout after ${timeout}ms (exceeded during execution)`));
2705
2717
  }, remainingTimeout);
2706
2718
  if (timeoutId && typeof timeoutId.unref === 'function') {
2707
2719
  timeoutId.unref();
@@ -3018,7 +3030,18 @@ class EtsyWebhookHandler {
3018
3030
  }
3019
3031
  }
3020
3032
  parseEvent(payload) {
3021
- const data = typeof payload === 'string' ? JSON.parse(payload) : payload;
3033
+ let data;
3034
+ if (typeof payload === 'string') {
3035
+ try {
3036
+ data = JSON.parse(payload);
3037
+ }
3038
+ catch {
3039
+ throw new Error('Invalid webhook payload: malformed JSON');
3040
+ }
3041
+ }
3042
+ else {
3043
+ data = payload;
3044
+ }
3022
3045
  if (!data.type || !data.data) {
3023
3046
  throw new Error('Invalid webhook event format');
3024
3047
  }
@@ -3408,7 +3431,6 @@ function createCacheStorage(config = {}) {
3408
3431
  case 'lfu':
3409
3432
  return new LFUCache(config);
3410
3433
  case 'ttl':
3411
- return new LRUCache(config);
3412
3434
  default:
3413
3435
  return new LRUCache(config);
3414
3436
  }
@@ -4223,7 +4245,7 @@ function createCachingPlugin(config = {}) {
4223
4245
  };
4224
4246
  }
4225
4247
  function createRateLimitPlugin(config = {}) {
4226
- const maxRequestsPerSecond = config.maxRequestsPerSecond || 10;
4248
+ const maxRequestsPerSecond = config.maxRequestsPerSecond || ETSY_RATE_LIMITS.MAX_REQUESTS_PER_SECOND;
4227
4249
  const requests = [];
4228
4250
  return {
4229
4251
  name: 'rateLimit',
@@ -4284,6 +4306,7 @@ exports.COMMON_SCOPE_COMBINATIONS = COMMON_SCOPE_COMBINATIONS;
4284
4306
  exports.CacheWithInvalidation = CacheWithInvalidation;
4285
4307
  exports.CreateListingSchema = CreateListingSchema;
4286
4308
  exports.DEFAULT_RETRY_CONFIG = DEFAULT_RETRY_CONFIG;
4309
+ exports.ETSY_RATE_LIMITS = ETSY_RATE_LIMITS;
4287
4310
  exports.ETSY_SCOPES = ETSY_SCOPES;
4288
4311
  exports.EncryptedFileTokenStorage = EncryptedFileTokenStorage;
4289
4312
  exports.EtsyApiError = EtsyApiError;