@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.esm.js
CHANGED
|
@@ -673,6 +673,11 @@ class FileTokenStorage {
|
|
|
673
673
|
}
|
|
674
674
|
}
|
|
675
675
|
|
|
676
|
+
const ETSY_RATE_LIMITS = {
|
|
677
|
+
MAX_REQUESTS_PER_DAY: 5000,
|
|
678
|
+
MAX_REQUESTS_PER_SECOND: 5,
|
|
679
|
+
MIN_REQUEST_INTERVAL: 200,
|
|
680
|
+
};
|
|
676
681
|
class EtsyRateLimiter {
|
|
677
682
|
constructor(config) {
|
|
678
683
|
this.requestCount = 0;
|
|
@@ -681,9 +686,9 @@ class EtsyRateLimiter {
|
|
|
681
686
|
this.isHeaderBasedLimiting = false;
|
|
682
687
|
this.currentRetryCount = 0;
|
|
683
688
|
this.config = {
|
|
684
|
-
maxRequestsPerDay:
|
|
685
|
-
maxRequestsPerSecond:
|
|
686
|
-
minRequestInterval:
|
|
689
|
+
maxRequestsPerDay: ETSY_RATE_LIMITS.MAX_REQUESTS_PER_DAY,
|
|
690
|
+
maxRequestsPerSecond: ETSY_RATE_LIMITS.MAX_REQUESTS_PER_SECOND,
|
|
691
|
+
minRequestInterval: ETSY_RATE_LIMITS.MIN_REQUEST_INTERVAL,
|
|
687
692
|
maxRetries: 3,
|
|
688
693
|
baseDelayMs: 1000,
|
|
689
694
|
maxDelayMs: 30000,
|
|
@@ -738,7 +743,7 @@ class EtsyRateLimiter {
|
|
|
738
743
|
if (value === null)
|
|
739
744
|
return undefined;
|
|
740
745
|
const num = parseInt(value, 10);
|
|
741
|
-
return isNaN(num) ? undefined : num;
|
|
746
|
+
return Number.isNaN(num) ? undefined : num;
|
|
742
747
|
};
|
|
743
748
|
return {
|
|
744
749
|
limitPerSecond: parseNumber(getHeader('x-limit-per-second')),
|
|
@@ -1079,7 +1084,7 @@ class FieldValidator {
|
|
|
1079
1084
|
const value = data[this.field];
|
|
1080
1085
|
if (value === undefined || value === null)
|
|
1081
1086
|
return null;
|
|
1082
|
-
if (typeof value !== 'number' || isNaN(value)) {
|
|
1087
|
+
if (typeof value !== 'number' || Number.isNaN(value)) {
|
|
1083
1088
|
return {
|
|
1084
1089
|
field: this.field,
|
|
1085
1090
|
message: options.message || `${this.field} must be a number`,
|
|
@@ -1288,9 +1293,14 @@ function combineValidators(...validators) {
|
|
|
1288
1293
|
|
|
1289
1294
|
class DefaultLogger {
|
|
1290
1295
|
debug(message, ...args) {
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1296
|
+
let isDevelopment;
|
|
1297
|
+
if (isNode$1) {
|
|
1298
|
+
isDevelopment = process.env.NODE_ENV === 'development';
|
|
1299
|
+
}
|
|
1300
|
+
else {
|
|
1301
|
+
const host = window.location?.hostname;
|
|
1302
|
+
isDevelopment = host === 'localhost' || host === '127.0.0.1';
|
|
1303
|
+
}
|
|
1294
1304
|
if (isDevelopment) {
|
|
1295
1305
|
console.log(`[DEBUG] ${message}`, ...args);
|
|
1296
1306
|
}
|
|
@@ -1332,6 +1342,9 @@ class MemoryCache {
|
|
|
1332
1342
|
}
|
|
1333
1343
|
class EtsyClient {
|
|
1334
1344
|
constructor(config) {
|
|
1345
|
+
if (!config.sharedSecret) {
|
|
1346
|
+
throw new EtsyAuthError('sharedSecret is REQUIRED for Etsy API v3 application usage. See: https://github.com/profplum700/etsy-v3-api-client/issues/21');
|
|
1347
|
+
}
|
|
1335
1348
|
this.tokenManager = new TokenManager(config);
|
|
1336
1349
|
this.baseUrl = config.baseUrl || 'https://api.etsy.com/v3/application';
|
|
1337
1350
|
this.logger = new DefaultLogger();
|
|
@@ -1339,9 +1352,9 @@ class EtsyClient {
|
|
|
1339
1352
|
this.sharedSecret = config.sharedSecret;
|
|
1340
1353
|
if (config.rateLimiting?.enabled !== false) {
|
|
1341
1354
|
this.rateLimiter = new EtsyRateLimiter({
|
|
1342
|
-
maxRequestsPerDay: config.rateLimiting?.maxRequestsPerDay ||
|
|
1343
|
-
maxRequestsPerSecond: config.rateLimiting?.maxRequestsPerSecond ||
|
|
1344
|
-
minRequestInterval: config.rateLimiting?.minRequestInterval ??
|
|
1355
|
+
maxRequestsPerDay: config.rateLimiting?.maxRequestsPerDay || ETSY_RATE_LIMITS.MAX_REQUESTS_PER_DAY,
|
|
1356
|
+
maxRequestsPerSecond: config.rateLimiting?.maxRequestsPerSecond || ETSY_RATE_LIMITS.MAX_REQUESTS_PER_SECOND,
|
|
1357
|
+
minRequestInterval: config.rateLimiting?.minRequestInterval ?? ETSY_RATE_LIMITS.MIN_REQUEST_INTERVAL,
|
|
1345
1358
|
maxRetries: config.rateLimiting?.maxRetries,
|
|
1346
1359
|
baseDelayMs: config.rateLimiting?.baseDelayMs,
|
|
1347
1360
|
maxDelayMs: config.rateLimiting?.maxDelayMs,
|
|
@@ -1372,7 +1385,12 @@ class EtsyClient {
|
|
|
1372
1385
|
if (useCache && this.cache && requestOptions.method === 'GET') {
|
|
1373
1386
|
const cached = await this.cache.get(cacheKey);
|
|
1374
1387
|
if (cached) {
|
|
1375
|
-
|
|
1388
|
+
try {
|
|
1389
|
+
return JSON.parse(cached);
|
|
1390
|
+
}
|
|
1391
|
+
catch {
|
|
1392
|
+
await this.cache.delete(cacheKey);
|
|
1393
|
+
}
|
|
1376
1394
|
}
|
|
1377
1395
|
}
|
|
1378
1396
|
await this.rateLimiter.waitForRateLimit();
|
|
@@ -1446,10 +1464,7 @@ class EtsyClient {
|
|
|
1446
1464
|
return body;
|
|
1447
1465
|
}
|
|
1448
1466
|
getApiKey() {
|
|
1449
|
-
|
|
1450
|
-
return `${this.keystring}:${this.sharedSecret}`;
|
|
1451
|
-
}
|
|
1452
|
-
return this.keystring;
|
|
1467
|
+
return `${this.keystring}:${this.sharedSecret}`;
|
|
1453
1468
|
}
|
|
1454
1469
|
async getUser() {
|
|
1455
1470
|
return this.makeRequest('/users/me');
|
|
@@ -2120,6 +2135,22 @@ class EtsyClient {
|
|
|
2120
2135
|
async deleteListingVideo(shopId, listingId, videoId) {
|
|
2121
2136
|
await this.makeRequest(`/shops/${shopId}/listings/${listingId}/videos/${videoId}`, { method: 'DELETE' }, false);
|
|
2122
2137
|
}
|
|
2138
|
+
async getListingPersonalizations(listingId) {
|
|
2139
|
+
return this.makeRequest(`/listings/${listingId}/personalization`);
|
|
2140
|
+
}
|
|
2141
|
+
async updateListingPersonalization(shopId, listingId, params) {
|
|
2142
|
+
const { supports_multiple_personalization_questions, ...body } = params;
|
|
2143
|
+
const query = supports_multiple_personalization_questions
|
|
2144
|
+
? '?supports_multiple_personalization_questions=true'
|
|
2145
|
+
: '';
|
|
2146
|
+
return this.makeRequest(`/shops/${shopId}/listings/${listingId}/personalization${query}`, {
|
|
2147
|
+
method: 'POST',
|
|
2148
|
+
body: JSON.stringify(body)
|
|
2149
|
+
}, false);
|
|
2150
|
+
}
|
|
2151
|
+
async deleteListingPersonalization(shopId, listingId) {
|
|
2152
|
+
await this.makeRequest(`/shops/${shopId}/listings/${listingId}/personalization`, { method: 'DELETE' }, false);
|
|
2153
|
+
}
|
|
2123
2154
|
async createListingTranslation(shopId, listingId, language, params) {
|
|
2124
2155
|
const body = this.buildFormBody(params);
|
|
2125
2156
|
return this.makeRequest(`/shops/${shopId}/listings/${listingId}/translations/${language}`, {
|
|
@@ -2602,9 +2633,9 @@ class GlobalRequestQueue {
|
|
|
2602
2633
|
this.requestCount = 0;
|
|
2603
2634
|
this.dailyReset = new Date();
|
|
2604
2635
|
this.lastRequestTime = 0;
|
|
2605
|
-
this.maxRequestsPerDay =
|
|
2606
|
-
this.maxRequestsPerSecond =
|
|
2607
|
-
this.minRequestInterval =
|
|
2636
|
+
this.maxRequestsPerDay = ETSY_RATE_LIMITS.MAX_REQUESTS_PER_DAY;
|
|
2637
|
+
this.maxRequestsPerSecond = ETSY_RATE_LIMITS.MAX_REQUESTS_PER_SECOND;
|
|
2638
|
+
this.minRequestInterval = ETSY_RATE_LIMITS.MIN_REQUEST_INTERVAL;
|
|
2608
2639
|
this.setNextDailyReset();
|
|
2609
2640
|
}
|
|
2610
2641
|
static getInstance() {
|
|
@@ -2689,11 +2720,12 @@ class GlobalRequestQueue {
|
|
|
2689
2720
|
try {
|
|
2690
2721
|
let result;
|
|
2691
2722
|
if (item.timeout) {
|
|
2692
|
-
const
|
|
2723
|
+
const timeout = item.timeout;
|
|
2724
|
+
const remainingTimeout = timeout - elapsed;
|
|
2693
2725
|
let timeoutId;
|
|
2694
2726
|
const timeoutPromise = new Promise((_, reject) => {
|
|
2695
2727
|
timeoutId = setTimeout(() => {
|
|
2696
|
-
reject(new Error(`Request timeout after ${
|
|
2728
|
+
reject(new Error(`Request timeout after ${timeout}ms (exceeded during execution)`));
|
|
2697
2729
|
}, remainingTimeout);
|
|
2698
2730
|
if (timeoutId && typeof timeoutId.unref === 'function') {
|
|
2699
2731
|
timeoutId.unref();
|
|
@@ -3010,7 +3042,18 @@ class EtsyWebhookHandler {
|
|
|
3010
3042
|
}
|
|
3011
3043
|
}
|
|
3012
3044
|
parseEvent(payload) {
|
|
3013
|
-
|
|
3045
|
+
let data;
|
|
3046
|
+
if (typeof payload === 'string') {
|
|
3047
|
+
try {
|
|
3048
|
+
data = JSON.parse(payload);
|
|
3049
|
+
}
|
|
3050
|
+
catch {
|
|
3051
|
+
throw new Error('Invalid webhook payload: malformed JSON');
|
|
3052
|
+
}
|
|
3053
|
+
}
|
|
3054
|
+
else {
|
|
3055
|
+
data = payload;
|
|
3056
|
+
}
|
|
3014
3057
|
if (!data.type || !data.data) {
|
|
3015
3058
|
throw new Error('Invalid webhook event format');
|
|
3016
3059
|
}
|
|
@@ -3400,7 +3443,6 @@ function createCacheStorage(config = {}) {
|
|
|
3400
3443
|
case 'lfu':
|
|
3401
3444
|
return new LFUCache(config);
|
|
3402
3445
|
case 'ttl':
|
|
3403
|
-
return new LRUCache(config);
|
|
3404
3446
|
default:
|
|
3405
3447
|
return new LRUCache(config);
|
|
3406
3448
|
}
|
|
@@ -4215,7 +4257,7 @@ function createCachingPlugin(config = {}) {
|
|
|
4215
4257
|
};
|
|
4216
4258
|
}
|
|
4217
4259
|
function createRateLimitPlugin(config = {}) {
|
|
4218
|
-
const maxRequestsPerSecond = config.maxRequestsPerSecond ||
|
|
4260
|
+
const maxRequestsPerSecond = config.maxRequestsPerSecond || ETSY_RATE_LIMITS.MAX_REQUESTS_PER_SECOND;
|
|
4219
4261
|
const requests = [];
|
|
4220
4262
|
return {
|
|
4221
4263
|
name: 'rateLimit',
|
|
@@ -4269,5 +4311,5 @@ function getLibraryInfo() {
|
|
|
4269
4311
|
};
|
|
4270
4312
|
}
|
|
4271
4313
|
|
|
4272
|
-
export { AuthHelper, BatchQueryExecutor, BulkOperationManager, COMMON_SCOPE_COMBINATIONS, CacheWithInvalidation, CreateListingSchema, DEFAULT_RETRY_CONFIG, ETSY_SCOPES, EncryptedFileTokenStorage, EtsyApiError, EtsyAuthError, EtsyClient, EtsyRateLimitError, EtsyRateLimiter, EtsyWebhookHandler, FieldValidator, FileTokenStorage, GlobalRequestQueue, LFUCache, LIBRARY_NAME, LRUCache, ListingQueryBuilder, LocalStorageTokenStorage, MemoryTokenStorage, PaginatedResults, PluginManager, ReceiptQueryBuilder, RedisCacheStorage, RetryManager, SecureTokenStorage, SessionStorageTokenStorage, TokenManager, UpdateListingSchema, UpdateShopSchema, VERSION, ValidationException, Validator, WebhookSecurity, combineValidators, createAnalyticsPlugin, createAuthHelper, createBatchQuery, createBulkOperationManager, createCacheStorage, createCacheWithInvalidation, createCachingPlugin, createCodeChallenge, createDefaultTokenStorage, createEtsyClient, createListingQuery, createLoggingPlugin, createPaginatedResults, createRateLimitPlugin, createRateLimiter, createReceiptQuery, createRedisCacheStorage, createRetryPlugin, createTokenManager, createValidator, createWebhookHandler, createWebhookSecurity, decryptAES256GCM, EtsyClient as default, defaultRateLimiter, deriveKeyFromPassword, encryptAES256GCM, executeBulkOperation, field, generateCodeVerifier, generateEncryptionKey, generateRandomBase64Url, generateState, getAvailableStorage, getEnvironmentInfo, getGlobalQueue, getLibraryInfo, hasLocalStorage, hasSessionStorage, isBrowser$1 as isBrowser, isNode$1 as isNode, isSecureStorageSupported, sha256, sha256Base64Url, validate, validateEncryptionKey, validateOrThrow, withQueryBuilder, withQueue, withRetry };
|
|
4314
|
+
export { AuthHelper, BatchQueryExecutor, BulkOperationManager, COMMON_SCOPE_COMBINATIONS, CacheWithInvalidation, CreateListingSchema, DEFAULT_RETRY_CONFIG, ETSY_RATE_LIMITS, ETSY_SCOPES, EncryptedFileTokenStorage, EtsyApiError, EtsyAuthError, EtsyClient, EtsyRateLimitError, EtsyRateLimiter, EtsyWebhookHandler, FieldValidator, FileTokenStorage, GlobalRequestQueue, LFUCache, LIBRARY_NAME, LRUCache, ListingQueryBuilder, LocalStorageTokenStorage, MemoryTokenStorage, PaginatedResults, PluginManager, ReceiptQueryBuilder, RedisCacheStorage, RetryManager, SecureTokenStorage, SessionStorageTokenStorage, TokenManager, UpdateListingSchema, UpdateShopSchema, VERSION, ValidationException, Validator, WebhookSecurity, combineValidators, createAnalyticsPlugin, createAuthHelper, createBatchQuery, createBulkOperationManager, createCacheStorage, createCacheWithInvalidation, createCachingPlugin, createCodeChallenge, createDefaultTokenStorage, createEtsyClient, createListingQuery, createLoggingPlugin, createPaginatedResults, createRateLimitPlugin, createRateLimiter, createReceiptQuery, createRedisCacheStorage, createRetryPlugin, createTokenManager, createValidator, createWebhookHandler, createWebhookSecurity, decryptAES256GCM, EtsyClient as default, defaultRateLimiter, deriveKeyFromPassword, encryptAES256GCM, executeBulkOperation, field, generateCodeVerifier, generateEncryptionKey, generateRandomBase64Url, generateState, getAvailableStorage, getEnvironmentInfo, getGlobalQueue, getLibraryInfo, hasLocalStorage, hasSessionStorage, isBrowser$1 as isBrowser, isNode$1 as isNode, isSecureStorageSupported, sha256, sha256Base64Url, validate, validateEncryptionKey, validateOrThrow, withQueryBuilder, withQueue, withRetry };
|
|
4273
4315
|
//# sourceMappingURL=node.esm.js.map
|