ebay-mcp 1.4.3
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/LICENSE +201 -0
- package/README.md +586 -0
- package/build/api/account-management/account.d.ts +216 -0
- package/build/api/account-management/account.js +305 -0
- package/build/api/analytics-and-report/analytics.d.ts +33 -0
- package/build/api/analytics-and-report/analytics.js +102 -0
- package/build/api/client.d.ts +89 -0
- package/build/api/client.js +343 -0
- package/build/api/communication/feedback.d.ts +45 -0
- package/build/api/communication/feedback.js +119 -0
- package/build/api/communication/message.d.ts +55 -0
- package/build/api/communication/message.js +131 -0
- package/build/api/communication/negotiation.d.ts +39 -0
- package/build/api/communication/negotiation.js +97 -0
- package/build/api/communication/notification.d.ts +128 -0
- package/build/api/communication/notification.js +373 -0
- package/build/api/index.d.ts +96 -0
- package/build/api/index.js +121 -0
- package/build/api/listing-management/inventory.d.ts +216 -0
- package/build/api/listing-management/inventory.js +633 -0
- package/build/api/listing-metadata/metadata.d.ts +154 -0
- package/build/api/listing-metadata/metadata.js +485 -0
- package/build/api/listing-metadata/taxonomy.d.ts +38 -0
- package/build/api/listing-metadata/taxonomy.js +58 -0
- package/build/api/marketing-and-promotions/marketing.d.ts +395 -0
- package/build/api/marketing-and-promotions/marketing.js +565 -0
- package/build/api/marketing-and-promotions/recommendation.d.ts +20 -0
- package/build/api/marketing-and-promotions/recommendation.js +32 -0
- package/build/api/order-management/dispute.d.ts +65 -0
- package/build/api/order-management/dispute.js +69 -0
- package/build/api/order-management/fulfillment.d.ts +80 -0
- package/build/api/order-management/fulfillment.js +89 -0
- package/build/api/other/compliance.d.ts +26 -0
- package/build/api/other/compliance.js +47 -0
- package/build/api/other/edelivery.d.ts +153 -0
- package/build/api/other/edelivery.js +219 -0
- package/build/api/other/identity.d.ts +17 -0
- package/build/api/other/identity.js +24 -0
- package/build/api/other/translation.d.ts +14 -0
- package/build/api/other/translation.js +22 -0
- package/build/api/other/vero.d.ts +30 -0
- package/build/api/other/vero.js +48 -0
- package/build/auth/oauth-metadata.d.ts +46 -0
- package/build/auth/oauth-metadata.js +59 -0
- package/build/auth/oauth-middleware.d.ts +35 -0
- package/build/auth/oauth-middleware.js +99 -0
- package/build/auth/oauth-types.d.ts +66 -0
- package/build/auth/oauth-types.js +4 -0
- package/build/auth/oauth.d.ts +93 -0
- package/build/auth/oauth.js +383 -0
- package/build/auth/scope-utils.d.ts +70 -0
- package/build/auth/scope-utils.js +304 -0
- package/build/auth/token-verifier.d.ts +57 -0
- package/build/auth/token-verifier.js +172 -0
- package/build/config/environment.d.ts +61 -0
- package/build/config/environment.js +260 -0
- package/build/index.d.ts +1 -0
- package/build/index.js +98 -0
- package/build/schemas/account-management/account.d.ts +5324 -0
- package/build/schemas/account-management/account.js +366 -0
- package/build/schemas/analytics/analytics.d.ts +167 -0
- package/build/schemas/analytics/analytics.js +191 -0
- package/build/schemas/communication/messages.d.ts +1872 -0
- package/build/schemas/communication/messages.js +348 -0
- package/build/schemas/fulfillment/orders.d.ts +4655 -0
- package/build/schemas/fulfillment/orders.js +317 -0
- package/build/schemas/index.d.ts +2100 -0
- package/build/schemas/index.js +68 -0
- package/build/schemas/inventory-management/inventory.d.ts +6419 -0
- package/build/schemas/inventory-management/inventory.js +450 -0
- package/build/schemas/marketing/marketing.d.ts +14181 -0
- package/build/schemas/marketing/marketing.js +1088 -0
- package/build/schemas/metadata/metadata.d.ts +5259 -0
- package/build/schemas/metadata/metadata.js +614 -0
- package/build/schemas/other/other-apis.d.ts +257 -0
- package/build/schemas/other/other-apis.js +372 -0
- package/build/schemas/taxonomy/taxonomy.d.ts +215 -0
- package/build/schemas/taxonomy/taxonomy.js +571 -0
- package/build/scripts/auto-setup.d.ts +12 -0
- package/build/scripts/auto-setup.js +277 -0
- package/build/scripts/diagnostics.d.ts +8 -0
- package/build/scripts/diagnostics.js +299 -0
- package/build/scripts/download-specs.d.ts +1 -0
- package/build/scripts/download-specs.js +116 -0
- package/build/scripts/interactive-setup.d.ts +21 -0
- package/build/scripts/interactive-setup.js +723 -0
- package/build/server-http.d.ts +11 -0
- package/build/server-http.js +361 -0
- package/build/tools/definitions/account-with-schemas.d.ts +39 -0
- package/build/tools/definitions/account-with-schemas.js +170 -0
- package/build/tools/definitions/account.d.ts +12 -0
- package/build/tools/definitions/account.js +428 -0
- package/build/tools/definitions/analytics.d.ts +25 -0
- package/build/tools/definitions/analytics.js +66 -0
- package/build/tools/definitions/communication.d.ts +12 -0
- package/build/tools/definitions/communication.js +151 -0
- package/build/tools/definitions/fulfillment.d.ts +12 -0
- package/build/tools/definitions/fulfillment.js +326 -0
- package/build/tools/definitions/index.d.ts +25 -0
- package/build/tools/definitions/index.js +37 -0
- package/build/tools/definitions/inventory.d.ts +12 -0
- package/build/tools/definitions/inventory.js +429 -0
- package/build/tools/definitions/marketing.d.ts +12 -0
- package/build/tools/definitions/marketing.js +1095 -0
- package/build/tools/definitions/metadata.d.ts +12 -0
- package/build/tools/definitions/metadata.js +188 -0
- package/build/tools/definitions/other.d.ts +13 -0
- package/build/tools/definitions/other.js +309 -0
- package/build/tools/definitions/taxonomy.d.ts +25 -0
- package/build/tools/definitions/taxonomy.js +64 -0
- package/build/tools/definitions/token-management.d.ts +35 -0
- package/build/tools/definitions/token-management.js +103 -0
- package/build/tools/index.d.ts +11 -0
- package/build/tools/index.js +1003 -0
- package/build/tools/schemas.d.ts +14764 -0
- package/build/tools/schemas.js +667 -0
- package/build/tools/tool-definitions.d.ts +35 -0
- package/build/tools/tool-definitions.js +3534 -0
- package/build/types/application-settings/developerAnalyticsV1BetaOas3.d.ts +197 -0
- package/build/types/application-settings/developerAnalyticsV1BetaOas3.js +5 -0
- package/build/types/application-settings/developerClientRegistrationV1Oas3.d.ts +155 -0
- package/build/types/application-settings/developerClientRegistrationV1Oas3.js +5 -0
- package/build/types/application-settings/developerKeyManagementV1Oas3.d.ts +246 -0
- package/build/types/application-settings/developerKeyManagementV1Oas3.js +5 -0
- package/build/types/ebay-enums.d.ts +1204 -0
- package/build/types/ebay-enums.js +1330 -0
- package/build/types/ebay.d.ts +143 -0
- package/build/types/ebay.js +123 -0
- package/build/types/index.d.ts +6 -0
- package/build/types/index.js +10 -0
- package/build/types/sell-apps/account-management/sellAccountV1Oas3.d.ts +2579 -0
- package/build/types/sell-apps/account-management/sellAccountV1Oas3.js +5 -0
- package/build/types/sell-apps/analytics-and-report/sellAnalyticsV1Oas3.d.ts +446 -0
- package/build/types/sell-apps/analytics-and-report/sellAnalyticsV1Oas3.js +5 -0
- package/build/types/sell-apps/communication/commerceFeedbackV1BetaOas3.d.ts +705 -0
- package/build/types/sell-apps/communication/commerceFeedbackV1BetaOas3.js +5 -0
- package/build/types/sell-apps/communication/commerceMessageV1Oas3.d.ts +590 -0
- package/build/types/sell-apps/communication/commerceMessageV1Oas3.js +5 -0
- package/build/types/sell-apps/communication/commerceNotificationV1Oas3.d.ts +1276 -0
- package/build/types/sell-apps/communication/commerceNotificationV1Oas3.js +5 -0
- package/build/types/sell-apps/communication/sellNegotiationV1Oas3.d.ts +277 -0
- package/build/types/sell-apps/communication/sellNegotiationV1Oas3.js +5 -0
- package/build/types/sell-apps/listing-management/sellInventoryV1Oas3.d.ts +3133 -0
- package/build/types/sell-apps/listing-management/sellInventoryV1Oas3.js +5 -0
- package/build/types/sell-apps/listing-metadata/sellMetadataV1Oas3.d.ts +2289 -0
- package/build/types/sell-apps/listing-metadata/sellMetadataV1Oas3.js +5 -0
- package/build/types/sell-apps/markeitng-and-promotions/sellMarketingV1Oas3.d.ts +6650 -0
- package/build/types/sell-apps/markeitng-and-promotions/sellMarketingV1Oas3.js +5 -0
- package/build/types/sell-apps/markeitng-and-promotions/sellRecommendationV1Oas3.d.ts +172 -0
- package/build/types/sell-apps/markeitng-and-promotions/sellRecommendationV1Oas3.js +5 -0
- package/build/types/sell-apps/order-management/sellFulfillmentV1Oas3.d.ts +1869 -0
- package/build/types/sell-apps/order-management/sellFulfillmentV1Oas3.js +5 -0
- package/build/types/sell-apps/other-apis/commerceIdentityV1Oas3.d.ts +178 -0
- package/build/types/sell-apps/other-apis/commerceIdentityV1Oas3.js +5 -0
- package/build/types/sell-apps/other-apis/commerceTranslationV1BetaOas3.d.ts +128 -0
- package/build/types/sell-apps/other-apis/commerceTranslationV1BetaOas3.js +5 -0
- package/build/types/sell-apps/other-apis/commerceVeroV1Oas3.d.ts +417 -0
- package/build/types/sell-apps/other-apis/commerceVeroV1Oas3.js +5 -0
- package/build/types/sell-apps/other-apis/sellComplianceV1Oas3.d.ts +273 -0
- package/build/types/sell-apps/other-apis/sellComplianceV1Oas3.js +5 -0
- package/build/types/sell-apps/other-apis/sellEdeliveryInternationalShippingOas3.d.ts +2537 -0
- package/build/types/sell-apps/other-apis/sellEdeliveryInternationalShippingOas3.js +5 -0
- package/build/types/sell-apps/other-apis/sellMarketingV1Oas3.d.ts +6650 -0
- package/build/types/sell-apps/other-apis/sellMarketingV1Oas3.js +5 -0
- package/build/types/sell-apps/other-apis/sellRecommendationV1Oas3.d.ts +172 -0
- package/build/types/sell-apps/other-apis/sellRecommendationV1Oas3.js +5 -0
- package/build/utils/account-management/account.d.ts +1094 -0
- package/build/utils/account-management/account.js +831 -0
- package/build/utils/communication/feedback.d.ts +152 -0
- package/build/utils/communication/feedback.js +216 -0
- package/build/utils/communication/message.d.ts +174 -0
- package/build/utils/communication/message.js +242 -0
- package/build/utils/communication/negotiation.d.ts +123 -0
- package/build/utils/communication/negotiation.js +150 -0
- package/build/utils/communication/notification.d.ts +370 -0
- package/build/utils/communication/notification.js +369 -0
- package/build/utils/date-converter.d.ts +59 -0
- package/build/utils/date-converter.js +160 -0
- package/build/utils/llm-client-detector.d.ts +54 -0
- package/build/utils/llm-client-detector.js +318 -0
- package/build/utils/oauth-helper.d.ts +37 -0
- package/build/utils/oauth-helper.js +315 -0
- package/build/utils/order-management/dispute.d.ts +346 -0
- package/build/utils/order-management/dispute.js +369 -0
- package/build/utils/order-management/fulfillment.d.ts +200 -0
- package/build/utils/order-management/fulfillment.js +205 -0
- package/build/utils/other/compliance.d.ts +49 -0
- package/build/utils/other/compliance.js +76 -0
- package/build/utils/other/edelivery.d.ts +310 -0
- package/build/utils/other/edelivery.js +241 -0
- package/build/utils/other/identity.d.ts +13 -0
- package/build/utils/other/identity.js +13 -0
- package/build/utils/other/translation.d.ts +28 -0
- package/build/utils/other/translation.js +41 -0
- package/build/utils/other/vero.d.ts +61 -0
- package/build/utils/other/vero.js +90 -0
- package/build/utils/scope-helper.d.ts +49 -0
- package/build/utils/scope-helper.js +207 -0
- package/build/utils/security-checker.d.ts +46 -0
- package/build/utils/security-checker.js +248 -0
- package/build/utils/setup-validator.d.ts +25 -0
- package/build/utils/setup-validator.js +305 -0
- package/build/utils/token-utils.d.ts +40 -0
- package/build/utils/token-utils.js +40 -0
- package/package.json +115 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { EbayOAuthClient } from '../auth/oauth.js';
|
|
2
|
+
import type { EbayConfig } from '../types/ebay.js';
|
|
3
|
+
import { type AxiosRequestConfig } from 'axios';
|
|
4
|
+
/**
|
|
5
|
+
* Base client for making eBay API requests
|
|
6
|
+
*/
|
|
7
|
+
export declare class EbayApiClient {
|
|
8
|
+
private httpClient;
|
|
9
|
+
private authClient;
|
|
10
|
+
private baseUrl;
|
|
11
|
+
private rateLimitTracker;
|
|
12
|
+
private config;
|
|
13
|
+
constructor(config: EbayConfig);
|
|
14
|
+
/**
|
|
15
|
+
* Validate that access token is available before making API request
|
|
16
|
+
*/
|
|
17
|
+
private validateAccessToken;
|
|
18
|
+
/**
|
|
19
|
+
* Make a GET request to eBay API
|
|
20
|
+
*/
|
|
21
|
+
get<T = unknown>(endpoint: string, params?: Record<string, unknown>, config?: AxiosRequestConfig): Promise<T>;
|
|
22
|
+
/**
|
|
23
|
+
* Make a POST request to eBay API
|
|
24
|
+
*/
|
|
25
|
+
post<T = unknown>(endpoint: string, data?: unknown, config?: AxiosRequestConfig): Promise<T>;
|
|
26
|
+
/**
|
|
27
|
+
* Make a PUT request to eBay API
|
|
28
|
+
*/
|
|
29
|
+
put<T = unknown>(endpoint: string, data?: unknown, config?: AxiosRequestConfig): Promise<T>;
|
|
30
|
+
/**
|
|
31
|
+
* Make a DELETE request to eBay API
|
|
32
|
+
*/
|
|
33
|
+
delete<T = unknown>(endpoint: string, config?: AxiosRequestConfig): Promise<T>;
|
|
34
|
+
/**
|
|
35
|
+
* Initialize the client (load user tokens from storage)
|
|
36
|
+
*/
|
|
37
|
+
initialize(): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Check if client is authenticated
|
|
40
|
+
*/
|
|
41
|
+
isAuthenticated(): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Check if user tokens are available
|
|
44
|
+
*/
|
|
45
|
+
hasUserTokens(): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Set user access and refresh tokens
|
|
48
|
+
*/
|
|
49
|
+
setUserTokens(accessToken: string, refreshToken: string): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Get token information for debugging
|
|
52
|
+
*/
|
|
53
|
+
getTokenInfo(): {
|
|
54
|
+
hasUserToken: boolean;
|
|
55
|
+
hasAppAccessToken: boolean;
|
|
56
|
+
scopeInfo?: {
|
|
57
|
+
tokenScopes: string[];
|
|
58
|
+
environmentScopes: string[];
|
|
59
|
+
missingScopes: string[];
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Get the OAuth client instance for advanced operations
|
|
64
|
+
*/
|
|
65
|
+
getOAuthClient(): EbayOAuthClient;
|
|
66
|
+
/**
|
|
67
|
+
* Get rate limit statistics
|
|
68
|
+
*/
|
|
69
|
+
getRateLimitStats(): {
|
|
70
|
+
current: number;
|
|
71
|
+
max: number;
|
|
72
|
+
windowMs: number;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Get the config object (for accessing environment, etc.)
|
|
76
|
+
*/
|
|
77
|
+
getConfig(): EbayConfig;
|
|
78
|
+
/**
|
|
79
|
+
* Manually refresh user access token using the refresh token
|
|
80
|
+
* This is useful when you encounter "Invalid access token" errors
|
|
81
|
+
* The token will be automatically saved to storage after refresh
|
|
82
|
+
*/
|
|
83
|
+
refreshUserToken(): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Make a GET request with a full URL (for APIs that use different base URLs)
|
|
86
|
+
* Used by Identity API which uses apiz subdomain
|
|
87
|
+
*/
|
|
88
|
+
getWithFullUrl<T = unknown>(fullUrl: string, params?: Record<string, unknown>): Promise<T>;
|
|
89
|
+
}
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import { EbayOAuthClient } from '../auth/oauth.js';
|
|
2
|
+
import { getBaseUrl } from '../config/environment.js';
|
|
3
|
+
import axios from 'axios';
|
|
4
|
+
/**
|
|
5
|
+
* Rate limit tracking
|
|
6
|
+
*/
|
|
7
|
+
class RateLimitTracker {
|
|
8
|
+
requestTimestamps = [];
|
|
9
|
+
windowMs = 60000; // 1 minute window
|
|
10
|
+
maxRequests = 5000; // Conservative limit
|
|
11
|
+
canMakeRequest() {
|
|
12
|
+
const now = Date.now();
|
|
13
|
+
// Remove timestamps older than window
|
|
14
|
+
this.requestTimestamps = this.requestTimestamps.filter((timestamp) => now - timestamp < this.windowMs);
|
|
15
|
+
return this.requestTimestamps.length < this.maxRequests;
|
|
16
|
+
}
|
|
17
|
+
recordRequest() {
|
|
18
|
+
this.requestTimestamps.push(Date.now());
|
|
19
|
+
}
|
|
20
|
+
getStats() {
|
|
21
|
+
const now = Date.now();
|
|
22
|
+
this.requestTimestamps = this.requestTimestamps.filter((timestamp) => now - timestamp < this.windowMs);
|
|
23
|
+
return {
|
|
24
|
+
current: this.requestTimestamps.length,
|
|
25
|
+
max: this.maxRequests,
|
|
26
|
+
windowMs: this.windowMs,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Base client for making eBay API requests
|
|
32
|
+
*/
|
|
33
|
+
export class EbayApiClient {
|
|
34
|
+
httpClient;
|
|
35
|
+
authClient;
|
|
36
|
+
baseUrl;
|
|
37
|
+
rateLimitTracker;
|
|
38
|
+
config;
|
|
39
|
+
constructor(config) {
|
|
40
|
+
this.config = config;
|
|
41
|
+
this.authClient = new EbayOAuthClient(config);
|
|
42
|
+
this.baseUrl = getBaseUrl(config.environment);
|
|
43
|
+
this.rateLimitTracker = new RateLimitTracker();
|
|
44
|
+
this.httpClient = axios.create({
|
|
45
|
+
baseURL: this.baseUrl,
|
|
46
|
+
timeout: 30000,
|
|
47
|
+
headers: {
|
|
48
|
+
'Content-Type': 'application/json',
|
|
49
|
+
Accept: 'application/json',
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
// Add request interceptor to inject auth token and check rate limits
|
|
53
|
+
this.httpClient.interceptors.request.use(async (config) => {
|
|
54
|
+
// Check rate limit before making request
|
|
55
|
+
if (!this.rateLimitTracker.canMakeRequest()) {
|
|
56
|
+
const stats = this.rateLimitTracker.getStats();
|
|
57
|
+
throw new Error(`Rate limit exceeded: ${stats.current}/${stats.max} requests in ${stats.windowMs}ms window. Please wait before making more requests.`);
|
|
58
|
+
}
|
|
59
|
+
const token = await this.authClient.getAccessToken();
|
|
60
|
+
config.headers.Authorization = `Bearer ${token}`;
|
|
61
|
+
// Record the request
|
|
62
|
+
this.rateLimitTracker.recordRequest();
|
|
63
|
+
// Debug logging: Log outgoing request details
|
|
64
|
+
console.error('\n🔍 [REQUEST DEBUG]');
|
|
65
|
+
console.error(` Method: ${config.method?.toUpperCase()}`);
|
|
66
|
+
console.error(` URL: ${config.baseURL}${config.url}`);
|
|
67
|
+
if (config.params && Object.keys(config.params).length > 0) {
|
|
68
|
+
console.error(` Query Params: ${JSON.stringify(config.params, null, 2)}`);
|
|
69
|
+
}
|
|
70
|
+
if (config.data) {
|
|
71
|
+
console.error(` Request Body: ${JSON.stringify(config.data, null, 2)}`);
|
|
72
|
+
}
|
|
73
|
+
return config;
|
|
74
|
+
}, (error) => console.error(error));
|
|
75
|
+
// Add response interceptor for error handling and retry logic
|
|
76
|
+
this.httpClient.interceptors.response.use((response) => {
|
|
77
|
+
// Extract rate limit info from headers if available
|
|
78
|
+
const remaining = response.headers['x-ebay-c-ratelimit-remaining'];
|
|
79
|
+
const limit = response.headers['x-ebay-c-ratelimit-limit'];
|
|
80
|
+
// Debug logging: Log response details
|
|
81
|
+
console.error('\n✅ [RESPONSE DEBUG]');
|
|
82
|
+
console.error(` Status: ${response.status} ${response.statusText}`);
|
|
83
|
+
if (remaining && limit) {
|
|
84
|
+
console.error(` Rate Limit: ${remaining}/${limit} remaining`);
|
|
85
|
+
}
|
|
86
|
+
if (response.data) {
|
|
87
|
+
const dataStr = JSON.stringify(response.data, null, 2);
|
|
88
|
+
const preview = dataStr.length > 500 ? dataStr.substring(0, 500) + '...' : dataStr;
|
|
89
|
+
console.error(` Response Data: ${preview}`);
|
|
90
|
+
}
|
|
91
|
+
return response;
|
|
92
|
+
}, async (error) => {
|
|
93
|
+
const axiosError = error;
|
|
94
|
+
const config = axiosError.config;
|
|
95
|
+
// Debug logging: Log error response details
|
|
96
|
+
if (axiosError.response) {
|
|
97
|
+
console.error('\n❌ [ERROR RESPONSE DEBUG]');
|
|
98
|
+
console.error(` Status: ${axiosError.response.status} ${axiosError.response.statusText}`);
|
|
99
|
+
console.error(` URL: ${config?.baseURL}${config?.url}`);
|
|
100
|
+
if (axiosError.response.data) {
|
|
101
|
+
console.error(` Error Data: ${JSON.stringify(axiosError.response.data, null, 2)}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
else if (axiosError.request) {
|
|
105
|
+
console.error('\n❌ [NO RESPONSE DEBUG]');
|
|
106
|
+
console.error(` Request was made but no response received`);
|
|
107
|
+
console.error(` URL: ${config?.baseURL}${config?.url}`);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
console.error('\n❌ [REQUEST ERROR DEBUG]');
|
|
111
|
+
console.error(` Error: ${axiosError.message}`);
|
|
112
|
+
}
|
|
113
|
+
// Handle authentication errors (401 Unauthorized)
|
|
114
|
+
if (axiosError.response?.status === 401) {
|
|
115
|
+
const retryCount = config?.__authRetryCount || 0;
|
|
116
|
+
// Only retry once to avoid infinite loops
|
|
117
|
+
if (retryCount === 0 && config) {
|
|
118
|
+
config.__authRetryCount = 1;
|
|
119
|
+
console.error('eBay API authentication error (401). Attempting to refresh user token...');
|
|
120
|
+
try {
|
|
121
|
+
// Force token refresh by getting a new access token
|
|
122
|
+
// The getAccessToken() method will automatically refresh if needed
|
|
123
|
+
const newToken = await this.authClient.getAccessToken();
|
|
124
|
+
// Update the request with the new token
|
|
125
|
+
if (config?.headers) {
|
|
126
|
+
config.headers.Authorization = `Bearer ${newToken}`;
|
|
127
|
+
}
|
|
128
|
+
console.error('Token refreshed successfully. Retrying request...');
|
|
129
|
+
// Retry the request with the new token
|
|
130
|
+
return await this.httpClient.request(config);
|
|
131
|
+
}
|
|
132
|
+
catch (refreshError) {
|
|
133
|
+
console.error('Failed to refresh token:', refreshError);
|
|
134
|
+
// If refresh fails, provide clear guidance
|
|
135
|
+
const ebayError = axiosError.response?.data;
|
|
136
|
+
const originalError = ebayError.errors?.[0]?.longMessage ||
|
|
137
|
+
ebayError.errors?.[0]?.message ||
|
|
138
|
+
'Invalid access token';
|
|
139
|
+
throw new Error(`${originalError}. ` +
|
|
140
|
+
`Token refresh failed: ${refreshError instanceof Error ? refreshError.message : 'Unknown error'}. ` +
|
|
141
|
+
`Please use the ebay_set_user_tokens_with_expiry tool to provide valid tokens.`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// If retry already attempted, provide helpful error message
|
|
145
|
+
const ebayError = axiosError.response?.data;
|
|
146
|
+
const errorMessage = ebayError.errors?.[0]?.longMessage ||
|
|
147
|
+
ebayError.errors?.[0]?.message ||
|
|
148
|
+
'Invalid access token';
|
|
149
|
+
throw new Error(`${errorMessage}. ` +
|
|
150
|
+
`Automatic token refresh failed. Please use the ebay_set_user_tokens_with_expiry tool to provide valid tokens.`);
|
|
151
|
+
}
|
|
152
|
+
// Handle rate limit errors (429)
|
|
153
|
+
if (axiosError.response?.status === 429) {
|
|
154
|
+
const retryAfter = axiosError.response.headers['retry-after'];
|
|
155
|
+
const waitTime = retryAfter ? parseInt(retryAfter) * 1000 : 60000;
|
|
156
|
+
throw new Error(`eBay API rate limit exceeded. Retry after ${waitTime / 1000} seconds. ` +
|
|
157
|
+
`Consider reducing request frequency or upgrading to user tokens for higher limits.`);
|
|
158
|
+
}
|
|
159
|
+
// Handle server errors with retry suggestion (500, 502, 503, 504)
|
|
160
|
+
if (axiosError.response?.status && axiosError.response.status >= 500 && config) {
|
|
161
|
+
const retryCount = config.__retryCount || 0;
|
|
162
|
+
if (retryCount < 3) {
|
|
163
|
+
config.__retryCount = retryCount + 1;
|
|
164
|
+
const delay = Math.pow(2, retryCount) * 1000; // Exponential backoff
|
|
165
|
+
console.error(`eBay API server error (${axiosError.response.status}). ` +
|
|
166
|
+
`Retrying in ${delay}ms (attempt ${retryCount + 1}/3)...`);
|
|
167
|
+
await new Promise((resolve) => setTimeout(resolve, Math.min(delay, 5000)));
|
|
168
|
+
return await this.httpClient.request(config);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// Handle eBay-specific errors
|
|
172
|
+
if (axios.isAxiosError(axiosError) && axiosError.response?.data) {
|
|
173
|
+
const ebayError = axiosError.response.data;
|
|
174
|
+
const errorMessage = ebayError.errors?.[0]?.longMessage ||
|
|
175
|
+
ebayError.errors?.[0]?.message ||
|
|
176
|
+
axiosError.message;
|
|
177
|
+
throw new Error(`eBay API Error: ${errorMessage}`);
|
|
178
|
+
}
|
|
179
|
+
throw error;
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Validate that access token is available before making API request
|
|
184
|
+
*/
|
|
185
|
+
validateAccessToken() {
|
|
186
|
+
if (!this.authClient.hasUserTokens()) {
|
|
187
|
+
throw new Error('Access token is missing. Please provide your access token and refresh token by calling ebay_set_user_tokens tool in order to perform API requests.');
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Make a GET request to eBay API
|
|
192
|
+
*/
|
|
193
|
+
async get(endpoint, params, config) {
|
|
194
|
+
this.validateAccessToken();
|
|
195
|
+
const response = await this.httpClient.get(endpoint, { params, ...config });
|
|
196
|
+
return response.data;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Make a POST request to eBay API
|
|
200
|
+
*/
|
|
201
|
+
async post(endpoint, data, config) {
|
|
202
|
+
this.validateAccessToken();
|
|
203
|
+
const response = await this.httpClient.post(endpoint, data, config);
|
|
204
|
+
return response.data;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Make a PUT request to eBay API
|
|
208
|
+
*/
|
|
209
|
+
async put(endpoint, data, config) {
|
|
210
|
+
this.validateAccessToken();
|
|
211
|
+
const response = await this.httpClient.put(endpoint, data, config);
|
|
212
|
+
return response.data;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Make a DELETE request to eBay API
|
|
216
|
+
*/
|
|
217
|
+
async delete(endpoint, config) {
|
|
218
|
+
this.validateAccessToken();
|
|
219
|
+
const response = await this.httpClient.delete(endpoint, config);
|
|
220
|
+
return response.data;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Initialize the client (load user tokens from storage)
|
|
224
|
+
*/
|
|
225
|
+
async initialize() {
|
|
226
|
+
await this.authClient.initialize();
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Check if client is authenticated
|
|
230
|
+
*/
|
|
231
|
+
isAuthenticated() {
|
|
232
|
+
return this.authClient.isAuthenticated();
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Check if user tokens are available
|
|
236
|
+
*/
|
|
237
|
+
hasUserTokens() {
|
|
238
|
+
return this.authClient.hasUserTokens();
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Set user access and refresh tokens
|
|
242
|
+
*/
|
|
243
|
+
async setUserTokens(accessToken, refreshToken) {
|
|
244
|
+
await this.authClient.setUserTokens(accessToken, refreshToken);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Get token information for debugging
|
|
248
|
+
*/
|
|
249
|
+
getTokenInfo() {
|
|
250
|
+
return this.authClient.getTokenInfo();
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Get the OAuth client instance for advanced operations
|
|
254
|
+
*/
|
|
255
|
+
getOAuthClient() {
|
|
256
|
+
return this.authClient;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Get rate limit statistics
|
|
260
|
+
*/
|
|
261
|
+
getRateLimitStats() {
|
|
262
|
+
return this.rateLimitTracker.getStats();
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Get the config object (for accessing environment, etc.)
|
|
266
|
+
*/
|
|
267
|
+
getConfig() {
|
|
268
|
+
return this.config;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Manually refresh user access token using the refresh token
|
|
272
|
+
* This is useful when you encounter "Invalid access token" errors
|
|
273
|
+
* The token will be automatically saved to storage after refresh
|
|
274
|
+
*/
|
|
275
|
+
async refreshUserToken() {
|
|
276
|
+
await this.authClient.refreshUserToken();
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Make a GET request with a full URL (for APIs that use different base URLs)
|
|
280
|
+
* Used by Identity API which uses apiz subdomain
|
|
281
|
+
*/
|
|
282
|
+
async getWithFullUrl(fullUrl, params) {
|
|
283
|
+
this.validateAccessToken();
|
|
284
|
+
// Check rate limit
|
|
285
|
+
if (!this.rateLimitTracker.canMakeRequest()) {
|
|
286
|
+
const stats = this.rateLimitTracker.getStats();
|
|
287
|
+
throw new Error(`Rate limit exceeded: ${stats.current}/${stats.max} requests in ${stats.windowMs}ms window. Please wait before making more requests.`);
|
|
288
|
+
}
|
|
289
|
+
// Get auth token
|
|
290
|
+
let token = await this.authClient.getAccessToken();
|
|
291
|
+
// Record the request
|
|
292
|
+
this.rateLimitTracker.recordRequest();
|
|
293
|
+
try {
|
|
294
|
+
// Make request with full URL
|
|
295
|
+
const response = await axios.get(fullUrl, {
|
|
296
|
+
params,
|
|
297
|
+
headers: {
|
|
298
|
+
Authorization: `Bearer ${token}`,
|
|
299
|
+
'Content-Type': 'application/json',
|
|
300
|
+
Accept: 'application/json',
|
|
301
|
+
},
|
|
302
|
+
timeout: 30000,
|
|
303
|
+
});
|
|
304
|
+
return response.data;
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
// Handle 401 authentication errors with automatic token refresh
|
|
308
|
+
if (axios.isAxiosError(error) && error.response?.status === 401) {
|
|
309
|
+
console.error('eBay API authentication error (401). Attempting to refresh user token...');
|
|
310
|
+
try {
|
|
311
|
+
// Refresh the token
|
|
312
|
+
await this.authClient.refreshUserToken();
|
|
313
|
+
// Get the new token
|
|
314
|
+
token = await this.authClient.getAccessToken();
|
|
315
|
+
console.error('Token refreshed successfully. Retrying request...');
|
|
316
|
+
// Retry the request with the new token
|
|
317
|
+
const response = await axios.get(fullUrl, {
|
|
318
|
+
params,
|
|
319
|
+
headers: {
|
|
320
|
+
Authorization: `Bearer ${token}`,
|
|
321
|
+
'Content-Type': 'application/json',
|
|
322
|
+
Accept: 'application/json',
|
|
323
|
+
},
|
|
324
|
+
timeout: 30000,
|
|
325
|
+
});
|
|
326
|
+
return response.data;
|
|
327
|
+
}
|
|
328
|
+
catch (refreshError) {
|
|
329
|
+
console.error('Failed to refresh token:', refreshError);
|
|
330
|
+
const ebayError = error.response?.data;
|
|
331
|
+
const originalError = ebayError.errors?.[0]?.longMessage ||
|
|
332
|
+
ebayError.errors?.[0]?.message ||
|
|
333
|
+
'Invalid access token';
|
|
334
|
+
throw new Error(`${originalError}. ` +
|
|
335
|
+
`Token refresh failed: ${refreshError instanceof Error ? refreshError.message : 'Unknown error'}. ` +
|
|
336
|
+
`Please use the ebay_set_user_tokens_with_expiry tool to provide valid tokens.`);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
// Re-throw other errors
|
|
340
|
+
throw error;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { EbayApiClient } from '../client.js';
|
|
2
|
+
/**
|
|
3
|
+
* Feedback API - Manage buyer and seller feedback
|
|
4
|
+
* Based on: docs/sell-apps/communication/commerce_feedback_v1_beta_oas3.json
|
|
5
|
+
*/
|
|
6
|
+
export declare class FeedbackApi {
|
|
7
|
+
private client;
|
|
8
|
+
private readonly basePath;
|
|
9
|
+
constructor(client: EbayApiClient);
|
|
10
|
+
/**
|
|
11
|
+
* Get items awaiting feedback
|
|
12
|
+
* Endpoint: GET /awaiting_feedback
|
|
13
|
+
* @throws Error if the request fails
|
|
14
|
+
*/
|
|
15
|
+
getAwaitingFeedback(filter?: string, limit?: number, offset?: number): Promise<unknown>;
|
|
16
|
+
/**
|
|
17
|
+
* Get feedback for a transaction
|
|
18
|
+
* Endpoint: GET /feedback
|
|
19
|
+
* @throws Error if required parameters are missing or invalid
|
|
20
|
+
*/
|
|
21
|
+
getFeedback(transactionId: string): Promise<unknown>;
|
|
22
|
+
/**
|
|
23
|
+
* Get feedback rating summary
|
|
24
|
+
* Endpoint: GET /feedback_rating_summary
|
|
25
|
+
* @throws Error if the request fails
|
|
26
|
+
*/
|
|
27
|
+
getFeedbackRatingSummary(): Promise<unknown>;
|
|
28
|
+
/**
|
|
29
|
+
* Leave feedback for a buyer
|
|
30
|
+
* Endpoint: POST /feedback
|
|
31
|
+
* @throws Error if required parameters are missing or invalid
|
|
32
|
+
*/
|
|
33
|
+
leaveFeedbackForBuyer(feedbackData: Record<string, unknown>): Promise<unknown>;
|
|
34
|
+
/**
|
|
35
|
+
* Respond to feedback
|
|
36
|
+
* Endpoint: POST /respond_to_feedback
|
|
37
|
+
* @throws Error if required parameters are missing or invalid
|
|
38
|
+
*/
|
|
39
|
+
respondToFeedback(feedbackId: string, responseText: string): Promise<unknown>;
|
|
40
|
+
/**
|
|
41
|
+
* Get feedback summary
|
|
42
|
+
* @deprecated Use getFeedbackRatingSummary() instead
|
|
43
|
+
*/
|
|
44
|
+
getFeedbackSummary(): Promise<unknown>;
|
|
45
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feedback API - Manage buyer and seller feedback
|
|
3
|
+
* Based on: docs/sell-apps/communication/commerce_feedback_v1_beta_oas3.json
|
|
4
|
+
*/
|
|
5
|
+
export class FeedbackApi {
|
|
6
|
+
client;
|
|
7
|
+
basePath = '/commerce/feedback/v1';
|
|
8
|
+
constructor(client) {
|
|
9
|
+
this.client = client;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Get items awaiting feedback
|
|
13
|
+
* Endpoint: GET /awaiting_feedback
|
|
14
|
+
* @throws Error if the request fails
|
|
15
|
+
*/
|
|
16
|
+
async getAwaitingFeedback(filter, limit, offset) {
|
|
17
|
+
const params = {};
|
|
18
|
+
if (filter !== undefined) {
|
|
19
|
+
if (typeof filter !== 'string') {
|
|
20
|
+
throw new Error('filter must be a string when provided');
|
|
21
|
+
}
|
|
22
|
+
params.filter = filter;
|
|
23
|
+
}
|
|
24
|
+
if (limit !== undefined) {
|
|
25
|
+
if (typeof limit !== 'number' || limit < 1) {
|
|
26
|
+
throw new Error('limit must be a positive number when provided');
|
|
27
|
+
}
|
|
28
|
+
params.limit = limit;
|
|
29
|
+
}
|
|
30
|
+
if (offset !== undefined) {
|
|
31
|
+
if (typeof offset !== 'number' || offset < 0) {
|
|
32
|
+
throw new Error('offset must be a non-negative number when provided');
|
|
33
|
+
}
|
|
34
|
+
params.offset = offset;
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
return await this.client.get(`${this.basePath}/awaiting_feedback`, params);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
throw new Error(`Failed to get awaiting feedback: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get feedback for a transaction
|
|
45
|
+
* Endpoint: GET /feedback
|
|
46
|
+
* @throws Error if required parameters are missing or invalid
|
|
47
|
+
*/
|
|
48
|
+
async getFeedback(transactionId) {
|
|
49
|
+
if (!transactionId || typeof transactionId !== 'string') {
|
|
50
|
+
throw new Error('transactionId is required and must be a string');
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
return await this.client.get(`${this.basePath}/feedback`, {
|
|
54
|
+
transaction_id: transactionId,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
throw new Error(`Failed to get feedback: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get feedback rating summary
|
|
63
|
+
* Endpoint: GET /feedback_rating_summary
|
|
64
|
+
* @throws Error if the request fails
|
|
65
|
+
*/
|
|
66
|
+
async getFeedbackRatingSummary() {
|
|
67
|
+
try {
|
|
68
|
+
return await this.client.get(`${this.basePath}/feedback_rating_summary`);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
throw new Error(`Failed to get feedback rating summary: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Leave feedback for a buyer
|
|
76
|
+
* Endpoint: POST /feedback
|
|
77
|
+
* @throws Error if required parameters are missing or invalid
|
|
78
|
+
*/
|
|
79
|
+
async leaveFeedbackForBuyer(feedbackData) {
|
|
80
|
+
if (!feedbackData || typeof feedbackData !== 'object') {
|
|
81
|
+
throw new Error('feedbackData is required and must be an object');
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
return await this.client.post(`${this.basePath}/feedback`, feedbackData);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
throw new Error(`Failed to leave feedback: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Respond to feedback
|
|
92
|
+
* Endpoint: POST /respond_to_feedback
|
|
93
|
+
* @throws Error if required parameters are missing or invalid
|
|
94
|
+
*/
|
|
95
|
+
async respondToFeedback(feedbackId, responseText) {
|
|
96
|
+
if (!feedbackId || typeof feedbackId !== 'string') {
|
|
97
|
+
throw new Error('feedbackId is required and must be a string');
|
|
98
|
+
}
|
|
99
|
+
if (!responseText || typeof responseText !== 'string') {
|
|
100
|
+
throw new Error('responseText is required and must be a string');
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
return await this.client.post(`${this.basePath}/respond_to_feedback`, {
|
|
104
|
+
feedback_id: feedbackId,
|
|
105
|
+
response_text: responseText,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
throw new Error(`Failed to respond to feedback: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get feedback summary
|
|
114
|
+
* @deprecated Use getFeedbackRatingSummary() instead
|
|
115
|
+
*/
|
|
116
|
+
async getFeedbackSummary() {
|
|
117
|
+
return await this.getFeedbackRatingSummary();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { EbayApiClient } from '../client.js';
|
|
2
|
+
/**
|
|
3
|
+
* Message API - Buyer-seller messaging
|
|
4
|
+
* Based on: docs/sell-apps/communication/commerce_message_v1_oas3.json
|
|
5
|
+
*/
|
|
6
|
+
export declare class MessageApi {
|
|
7
|
+
private client;
|
|
8
|
+
private readonly basePath;
|
|
9
|
+
constructor(client: EbayApiClient);
|
|
10
|
+
/**
|
|
11
|
+
* Bulk update conversation
|
|
12
|
+
* Endpoint: POST /bulk_update_conversation
|
|
13
|
+
* @throws Error if required parameters are missing or invalid
|
|
14
|
+
*/
|
|
15
|
+
bulkUpdateConversation(updateData: Record<string, unknown>): Promise<unknown>;
|
|
16
|
+
/**
|
|
17
|
+
* Get conversations
|
|
18
|
+
* Endpoint: GET /conversation
|
|
19
|
+
* @throws Error if the request fails
|
|
20
|
+
*/
|
|
21
|
+
getConversations(filter?: string, limit?: number, offset?: number): Promise<unknown>;
|
|
22
|
+
/**
|
|
23
|
+
* Get a specific conversation
|
|
24
|
+
* Endpoint: GET /conversation/{conversation_id}
|
|
25
|
+
* @throws Error if required parameters are missing or invalid
|
|
26
|
+
*/
|
|
27
|
+
getConversation(conversationId: string): Promise<unknown>;
|
|
28
|
+
/**
|
|
29
|
+
* Send a message
|
|
30
|
+
* Endpoint: POST /send_message
|
|
31
|
+
* @throws Error if required parameters are missing or invalid
|
|
32
|
+
*/
|
|
33
|
+
sendMessage(messageData: Record<string, unknown>): Promise<unknown>;
|
|
34
|
+
/**
|
|
35
|
+
* Update a conversation
|
|
36
|
+
* Endpoint: POST /update_conversation
|
|
37
|
+
* @throws Error if required parameters are missing or invalid
|
|
38
|
+
*/
|
|
39
|
+
updateConversation(updateData: Record<string, unknown>): Promise<unknown>;
|
|
40
|
+
/**
|
|
41
|
+
* Search for messages
|
|
42
|
+
* @deprecated Use getConversations() instead
|
|
43
|
+
*/
|
|
44
|
+
searchMessages(filter?: string, limit?: number, offset?: number): Promise<unknown>;
|
|
45
|
+
/**
|
|
46
|
+
* Get a specific message
|
|
47
|
+
* @deprecated Use getConversation() instead
|
|
48
|
+
*/
|
|
49
|
+
getMessage(messageId: string): Promise<unknown>;
|
|
50
|
+
/**
|
|
51
|
+
* Reply to a message
|
|
52
|
+
* @deprecated Use sendMessage() instead
|
|
53
|
+
*/
|
|
54
|
+
replyToMessage(messageId: string, messageContent: string): Promise<unknown>;
|
|
55
|
+
}
|