@profplum700/etsy-v3-api-client 2.5.3 → 3.0.0
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/CHANGELOG.md +21 -12
- package/README.md +138 -130
- package/dist/.tsbuildinfo +1 -1
- package/dist/browser.esm.js +64 -23
- package/dist/browser.esm.js.map +1 -1
- package/dist/browser.umd.js +1 -1
- package/dist/browser.umd.js.map +1 -1
- package/dist/index.cjs +67 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +39 -5
- package/dist/index.esm.js +67 -25
- package/dist/index.esm.js.map +1 -1
- package/dist/node.cjs +67 -24
- package/dist/node.cjs.map +1 -1
- package/dist/node.esm.js +67 -25
- package/dist/node.esm.js.map +1 -1
- package/package.json +1 -1
- package/dist/index.js +0 -8517
- package/dist/index.js.map +0 -1
- package/dist/index.umd.js +0 -1180
- package/dist/index.umd.js.map +0 -1
- package/dist/index.umd.min.js +0 -2
- package/dist/index.umd.min.js.map +0 -1
package/dist/node.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:
|
|
689
|
-
maxRequestsPerSecond:
|
|
690
|
-
minRequestInterval:
|
|
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
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
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
|
}
|
|
@@ -1336,6 +1346,9 @@ class MemoryCache {
|
|
|
1336
1346
|
}
|
|
1337
1347
|
class EtsyClient {
|
|
1338
1348
|
constructor(config) {
|
|
1349
|
+
if (!config.sharedSecret) {
|
|
1350
|
+
throw new EtsyAuthError('sharedSecret is REQUIRED for Etsy API v3 application usage. See: https://github.com/profplum700/etsy-v3-api-client/issues/21');
|
|
1351
|
+
}
|
|
1339
1352
|
this.tokenManager = new TokenManager(config);
|
|
1340
1353
|
this.baseUrl = config.baseUrl || 'https://api.etsy.com/v3/application';
|
|
1341
1354
|
this.logger = new DefaultLogger();
|
|
@@ -1343,9 +1356,9 @@ class EtsyClient {
|
|
|
1343
1356
|
this.sharedSecret = config.sharedSecret;
|
|
1344
1357
|
if (config.rateLimiting?.enabled !== false) {
|
|
1345
1358
|
this.rateLimiter = new EtsyRateLimiter({
|
|
1346
|
-
maxRequestsPerDay: config.rateLimiting?.maxRequestsPerDay ||
|
|
1347
|
-
maxRequestsPerSecond: config.rateLimiting?.maxRequestsPerSecond ||
|
|
1348
|
-
minRequestInterval: config.rateLimiting?.minRequestInterval ??
|
|
1359
|
+
maxRequestsPerDay: config.rateLimiting?.maxRequestsPerDay || ETSY_RATE_LIMITS.MAX_REQUESTS_PER_DAY,
|
|
1360
|
+
maxRequestsPerSecond: config.rateLimiting?.maxRequestsPerSecond || ETSY_RATE_LIMITS.MAX_REQUESTS_PER_SECOND,
|
|
1361
|
+
minRequestInterval: config.rateLimiting?.minRequestInterval ?? ETSY_RATE_LIMITS.MIN_REQUEST_INTERVAL,
|
|
1349
1362
|
maxRetries: config.rateLimiting?.maxRetries,
|
|
1350
1363
|
baseDelayMs: config.rateLimiting?.baseDelayMs,
|
|
1351
1364
|
maxDelayMs: config.rateLimiting?.maxDelayMs,
|
|
@@ -1376,7 +1389,12 @@ class EtsyClient {
|
|
|
1376
1389
|
if (useCache && this.cache && requestOptions.method === 'GET') {
|
|
1377
1390
|
const cached = await this.cache.get(cacheKey);
|
|
1378
1391
|
if (cached) {
|
|
1379
|
-
|
|
1392
|
+
try {
|
|
1393
|
+
return JSON.parse(cached);
|
|
1394
|
+
}
|
|
1395
|
+
catch {
|
|
1396
|
+
await this.cache.delete(cacheKey);
|
|
1397
|
+
}
|
|
1380
1398
|
}
|
|
1381
1399
|
}
|
|
1382
1400
|
await this.rateLimiter.waitForRateLimit();
|
|
@@ -1450,10 +1468,7 @@ class EtsyClient {
|
|
|
1450
1468
|
return body;
|
|
1451
1469
|
}
|
|
1452
1470
|
getApiKey() {
|
|
1453
|
-
|
|
1454
|
-
return `${this.keystring}:${this.sharedSecret}`;
|
|
1455
|
-
}
|
|
1456
|
-
return this.keystring;
|
|
1471
|
+
return `${this.keystring}:${this.sharedSecret}`;
|
|
1457
1472
|
}
|
|
1458
1473
|
async getUser() {
|
|
1459
1474
|
return this.makeRequest('/users/me');
|
|
@@ -2124,6 +2139,22 @@ class EtsyClient {
|
|
|
2124
2139
|
async deleteListingVideo(shopId, listingId, videoId) {
|
|
2125
2140
|
await this.makeRequest(`/shops/${shopId}/listings/${listingId}/videos/${videoId}`, { method: 'DELETE' }, false);
|
|
2126
2141
|
}
|
|
2142
|
+
async getListingPersonalizations(listingId) {
|
|
2143
|
+
return this.makeRequest(`/listings/${listingId}/personalization`);
|
|
2144
|
+
}
|
|
2145
|
+
async updateListingPersonalization(shopId, listingId, params) {
|
|
2146
|
+
const { supports_multiple_personalization_questions, ...body } = params;
|
|
2147
|
+
const query = supports_multiple_personalization_questions
|
|
2148
|
+
? '?supports_multiple_personalization_questions=true'
|
|
2149
|
+
: '';
|
|
2150
|
+
return this.makeRequest(`/shops/${shopId}/listings/${listingId}/personalization${query}`, {
|
|
2151
|
+
method: 'POST',
|
|
2152
|
+
body: JSON.stringify(body)
|
|
2153
|
+
}, false);
|
|
2154
|
+
}
|
|
2155
|
+
async deleteListingPersonalization(shopId, listingId) {
|
|
2156
|
+
await this.makeRequest(`/shops/${shopId}/listings/${listingId}/personalization`, { method: 'DELETE' }, false);
|
|
2157
|
+
}
|
|
2127
2158
|
async createListingTranslation(shopId, listingId, language, params) {
|
|
2128
2159
|
const body = this.buildFormBody(params);
|
|
2129
2160
|
return this.makeRequest(`/shops/${shopId}/listings/${listingId}/translations/${language}`, {
|
|
@@ -2606,9 +2637,9 @@ class GlobalRequestQueue {
|
|
|
2606
2637
|
this.requestCount = 0;
|
|
2607
2638
|
this.dailyReset = new Date();
|
|
2608
2639
|
this.lastRequestTime = 0;
|
|
2609
|
-
this.maxRequestsPerDay =
|
|
2610
|
-
this.maxRequestsPerSecond =
|
|
2611
|
-
this.minRequestInterval =
|
|
2640
|
+
this.maxRequestsPerDay = ETSY_RATE_LIMITS.MAX_REQUESTS_PER_DAY;
|
|
2641
|
+
this.maxRequestsPerSecond = ETSY_RATE_LIMITS.MAX_REQUESTS_PER_SECOND;
|
|
2642
|
+
this.minRequestInterval = ETSY_RATE_LIMITS.MIN_REQUEST_INTERVAL;
|
|
2612
2643
|
this.setNextDailyReset();
|
|
2613
2644
|
}
|
|
2614
2645
|
static getInstance() {
|
|
@@ -2693,11 +2724,12 @@ class GlobalRequestQueue {
|
|
|
2693
2724
|
try {
|
|
2694
2725
|
let result;
|
|
2695
2726
|
if (item.timeout) {
|
|
2696
|
-
const
|
|
2727
|
+
const timeout = item.timeout;
|
|
2728
|
+
const remainingTimeout = timeout - elapsed;
|
|
2697
2729
|
let timeoutId;
|
|
2698
2730
|
const timeoutPromise = new Promise((_, reject) => {
|
|
2699
2731
|
timeoutId = setTimeout(() => {
|
|
2700
|
-
reject(new Error(`Request timeout after ${
|
|
2732
|
+
reject(new Error(`Request timeout after ${timeout}ms (exceeded during execution)`));
|
|
2701
2733
|
}, remainingTimeout);
|
|
2702
2734
|
if (timeoutId && typeof timeoutId.unref === 'function') {
|
|
2703
2735
|
timeoutId.unref();
|
|
@@ -3014,7 +3046,18 @@ class EtsyWebhookHandler {
|
|
|
3014
3046
|
}
|
|
3015
3047
|
}
|
|
3016
3048
|
parseEvent(payload) {
|
|
3017
|
-
|
|
3049
|
+
let data;
|
|
3050
|
+
if (typeof payload === 'string') {
|
|
3051
|
+
try {
|
|
3052
|
+
data = JSON.parse(payload);
|
|
3053
|
+
}
|
|
3054
|
+
catch {
|
|
3055
|
+
throw new Error('Invalid webhook payload: malformed JSON');
|
|
3056
|
+
}
|
|
3057
|
+
}
|
|
3058
|
+
else {
|
|
3059
|
+
data = payload;
|
|
3060
|
+
}
|
|
3018
3061
|
if (!data.type || !data.data) {
|
|
3019
3062
|
throw new Error('Invalid webhook event format');
|
|
3020
3063
|
}
|
|
@@ -3404,7 +3447,6 @@ function createCacheStorage(config = {}) {
|
|
|
3404
3447
|
case 'lfu':
|
|
3405
3448
|
return new LFUCache(config);
|
|
3406
3449
|
case 'ttl':
|
|
3407
|
-
return new LRUCache(config);
|
|
3408
3450
|
default:
|
|
3409
3451
|
return new LRUCache(config);
|
|
3410
3452
|
}
|
|
@@ -4219,7 +4261,7 @@ function createCachingPlugin(config = {}) {
|
|
|
4219
4261
|
};
|
|
4220
4262
|
}
|
|
4221
4263
|
function createRateLimitPlugin(config = {}) {
|
|
4222
|
-
const maxRequestsPerSecond = config.maxRequestsPerSecond ||
|
|
4264
|
+
const maxRequestsPerSecond = config.maxRequestsPerSecond || ETSY_RATE_LIMITS.MAX_REQUESTS_PER_SECOND;
|
|
4223
4265
|
const requests = [];
|
|
4224
4266
|
return {
|
|
4225
4267
|
name: 'rateLimit',
|
|
@@ -4280,6 +4322,7 @@ exports.COMMON_SCOPE_COMBINATIONS = COMMON_SCOPE_COMBINATIONS;
|
|
|
4280
4322
|
exports.CacheWithInvalidation = CacheWithInvalidation;
|
|
4281
4323
|
exports.CreateListingSchema = CreateListingSchema;
|
|
4282
4324
|
exports.DEFAULT_RETRY_CONFIG = DEFAULT_RETRY_CONFIG;
|
|
4325
|
+
exports.ETSY_RATE_LIMITS = ETSY_RATE_LIMITS;
|
|
4283
4326
|
exports.ETSY_SCOPES = ETSY_SCOPES;
|
|
4284
4327
|
exports.EncryptedFileTokenStorage = EncryptedFileTokenStorage;
|
|
4285
4328
|
exports.EtsyApiError = EtsyApiError;
|