ebay-mcp-remote-edition 3.1.2 → 3.3.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/LICENSE +1 -1
- package/README.md +242 -3
- package/build/api/analytics-and-report/analytics.js +4 -4
- package/build/api/client-trading.js +2 -2
- package/build/api/communication/feedback.js +5 -5
- package/build/api/communication/message.js +5 -5
- package/build/api/communication/negotiation.js +3 -3
- package/build/api/communication/notification.js +21 -21
- package/build/api/listing-management/inventory.js +36 -36
- package/build/api/listing-metadata/metadata.js +24 -24
- package/build/auth/multi-user-store.js +8 -2
- package/build/auth/oauth.js +33 -7
- package/build/auth/token-verifier.js +3 -3
- package/build/config/environment.js +10 -0
- package/build/scripts/{run-with-local-env.js → env-check.js} +1 -1
- package/build/server-http.js +286 -90
- package/build/tools/chat-tools.js +50 -0
- package/build/tools/index.js +50 -9
- package/build/utils/version.js +1 -1
- package/build/validation/providers/chart.js +3 -0
- package/build/validation/providers/ebay-sold.js +216 -0
- package/build/validation/providers/ebay.js +170 -0
- package/build/validation/providers/query-utils.js +454 -0
- package/build/validation/providers/research.js +14 -0
- package/build/validation/providers/social.js +683 -0
- package/build/validation/providers/terapeak.js +30 -0
- package/build/validation/recommendation.js +100 -0
- package/build/validation/run-validation.js +374 -0
- package/build/validation/schemas.js +105 -0
- package/build/validation/types.js +1 -0
- package/package.json +29 -27
|
@@ -27,7 +27,7 @@ export class MetadataApi {
|
|
|
27
27
|
return await this.client.get(`${this.basePath}/marketplace/${marketplaceId}/get_automotive_parts_compatibility_policies`, params);
|
|
28
28
|
}
|
|
29
29
|
catch (error) {
|
|
30
|
-
throw new Error(`Failed to get automotive parts compatibility policies: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
30
|
+
throw new Error(`Failed to get automotive parts compatibility policies: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
@@ -49,7 +49,7 @@ export class MetadataApi {
|
|
|
49
49
|
return await this.client.get(`${this.basePath}/marketplace/${marketplaceId}/get_category_policies`, params);
|
|
50
50
|
}
|
|
51
51
|
catch (error) {
|
|
52
|
-
throw new Error(`Failed to get category policies: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
52
|
+
throw new Error(`Failed to get category policies: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
@@ -71,7 +71,7 @@ export class MetadataApi {
|
|
|
71
71
|
return await this.client.get(`${this.basePath}/marketplace/${marketplaceId}/get_extended_producer_responsibility_policies`, params);
|
|
72
72
|
}
|
|
73
73
|
catch (error) {
|
|
74
|
-
throw new Error(`Failed to get extended producer responsibility policies: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
74
|
+
throw new Error(`Failed to get extended producer responsibility policies: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
/**
|
|
@@ -87,7 +87,7 @@ export class MetadataApi {
|
|
|
87
87
|
return await this.client.get(`${this.basePath}/marketplace/${marketplaceId}/get_hazardous_materials_labels`);
|
|
88
88
|
}
|
|
89
89
|
catch (error) {
|
|
90
|
-
throw new Error(`Failed to get hazardous materials labels: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
90
|
+
throw new Error(`Failed to get hazardous materials labels: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
/**
|
|
@@ -109,7 +109,7 @@ export class MetadataApi {
|
|
|
109
109
|
return await this.client.get(`${this.basePath}/marketplace/${marketplaceId}/get_item_condition_policies`, params);
|
|
110
110
|
}
|
|
111
111
|
catch (error) {
|
|
112
|
-
throw new Error(`Failed to get item condition policies: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
112
|
+
throw new Error(`Failed to get item condition policies: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
/**
|
|
@@ -131,7 +131,7 @@ export class MetadataApi {
|
|
|
131
131
|
return await this.client.get(`${this.basePath}/marketplace/${marketplaceId}/get_listing_structure_policies`, params);
|
|
132
132
|
}
|
|
133
133
|
catch (error) {
|
|
134
|
-
throw new Error(`Failed to get listing structure policies: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
134
|
+
throw new Error(`Failed to get listing structure policies: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
/**
|
|
@@ -153,7 +153,7 @@ export class MetadataApi {
|
|
|
153
153
|
return await this.client.get(`${this.basePath}/marketplace/${marketplaceId}/get_negotiated_price_policies`, params);
|
|
154
154
|
}
|
|
155
155
|
catch (error) {
|
|
156
|
-
throw new Error(`Failed to get negotiated price policies: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
156
|
+
throw new Error(`Failed to get negotiated price policies: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
/**
|
|
@@ -169,7 +169,7 @@ export class MetadataApi {
|
|
|
169
169
|
return await this.client.get(`${this.basePath}/marketplace/${marketplaceId}/get_product_safety_labels`);
|
|
170
170
|
}
|
|
171
171
|
catch (error) {
|
|
172
|
-
throw new Error(`Failed to get product safety labels: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
172
|
+
throw new Error(`Failed to get product safety labels: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
/**
|
|
@@ -191,7 +191,7 @@ export class MetadataApi {
|
|
|
191
191
|
return await this.client.get(`${this.basePath}/marketplace/${marketplaceId}/get_regulatory_policies`, params);
|
|
192
192
|
}
|
|
193
193
|
catch (error) {
|
|
194
|
-
throw new Error(`Failed to get regulatory policies: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
194
|
+
throw new Error(`Failed to get regulatory policies: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
195
195
|
}
|
|
196
196
|
}
|
|
197
197
|
/**
|
|
@@ -213,7 +213,7 @@ export class MetadataApi {
|
|
|
213
213
|
return await this.client.get(`${this.basePath}/marketplace/${marketplaceId}/get_return_policies`, params);
|
|
214
214
|
}
|
|
215
215
|
catch (error) {
|
|
216
|
-
throw new Error(`Failed to get return policies: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
216
|
+
throw new Error(`Failed to get return policies: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
217
217
|
}
|
|
218
218
|
}
|
|
219
219
|
/**
|
|
@@ -235,7 +235,7 @@ export class MetadataApi {
|
|
|
235
235
|
return await this.client.get(`${this.basePath}/marketplace/${marketplaceId}/get_shipping_cost_type_policies`, params);
|
|
236
236
|
}
|
|
237
237
|
catch (error) {
|
|
238
|
-
throw new Error(`Failed to get shipping cost type policies: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
238
|
+
throw new Error(`Failed to get shipping cost type policies: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
241
|
/**
|
|
@@ -257,7 +257,7 @@ export class MetadataApi {
|
|
|
257
257
|
return await this.client.get(`${this.basePath}/marketplace/${marketplaceId}/get_classified_ad_policies`, params);
|
|
258
258
|
}
|
|
259
259
|
catch (error) {
|
|
260
|
-
throw new Error(`Failed to get classified ad policies: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
260
|
+
throw new Error(`Failed to get classified ad policies: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
/**
|
|
@@ -273,7 +273,7 @@ export class MetadataApi {
|
|
|
273
273
|
return await this.client.get(`${this.basePath}/marketplace/${marketplaceId}/get_currencies`);
|
|
274
274
|
}
|
|
275
275
|
catch (error) {
|
|
276
|
-
throw new Error(`Failed to get currencies: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
276
|
+
throw new Error(`Failed to get currencies: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
277
277
|
}
|
|
278
278
|
}
|
|
279
279
|
/**
|
|
@@ -295,7 +295,7 @@ export class MetadataApi {
|
|
|
295
295
|
return await this.client.get(`${this.basePath}/marketplace/${marketplaceId}/get_listing_type_policies`, params);
|
|
296
296
|
}
|
|
297
297
|
catch (error) {
|
|
298
|
-
throw new Error(`Failed to get listing type policies: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
298
|
+
throw new Error(`Failed to get listing type policies: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
299
299
|
}
|
|
300
300
|
}
|
|
301
301
|
/**
|
|
@@ -317,7 +317,7 @@ export class MetadataApi {
|
|
|
317
317
|
return await this.client.get(`${this.basePath}/marketplace/${marketplaceId}/get_motors_listing_policies`, params);
|
|
318
318
|
}
|
|
319
319
|
catch (error) {
|
|
320
|
-
throw new Error(`Failed to get motors listing policies: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
320
|
+
throw new Error(`Failed to get motors listing policies: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
321
321
|
}
|
|
322
322
|
}
|
|
323
323
|
/**
|
|
@@ -339,7 +339,7 @@ export class MetadataApi {
|
|
|
339
339
|
return await this.client.get(`${this.basePath}/marketplace/${marketplaceId}/get_shipping_policies`, params);
|
|
340
340
|
}
|
|
341
341
|
catch (error) {
|
|
342
|
-
throw new Error(`Failed to get shipping policies: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
342
|
+
throw new Error(`Failed to get shipping policies: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
343
343
|
}
|
|
344
344
|
}
|
|
345
345
|
/**
|
|
@@ -361,7 +361,7 @@ export class MetadataApi {
|
|
|
361
361
|
return await this.client.get(`${this.basePath}/marketplace/${marketplaceId}/get_site_visibility_policies`, params);
|
|
362
362
|
}
|
|
363
363
|
catch (error) {
|
|
364
|
-
throw new Error(`Failed to get site visibility policies: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
364
|
+
throw new Error(`Failed to get site visibility policies: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
365
365
|
}
|
|
366
366
|
}
|
|
367
367
|
/**
|
|
@@ -377,7 +377,7 @@ export class MetadataApi {
|
|
|
377
377
|
return await this.client.post(`${this.basePath}/compatibilities/get_compatibilities_by_specification`, specification);
|
|
378
378
|
}
|
|
379
379
|
catch (error) {
|
|
380
|
-
throw new Error(`Failed to get compatibilities by specification: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
380
|
+
throw new Error(`Failed to get compatibilities by specification: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
381
381
|
}
|
|
382
382
|
}
|
|
383
383
|
/**
|
|
@@ -393,7 +393,7 @@ export class MetadataApi {
|
|
|
393
393
|
return await this.client.post(`${this.basePath}/compatibilities/get_compatibility_property_names`, data);
|
|
394
394
|
}
|
|
395
395
|
catch (error) {
|
|
396
|
-
throw new Error(`Failed to get compatibility property names: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
396
|
+
throw new Error(`Failed to get compatibility property names: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
397
397
|
}
|
|
398
398
|
}
|
|
399
399
|
/**
|
|
@@ -409,7 +409,7 @@ export class MetadataApi {
|
|
|
409
409
|
return await this.client.post(`${this.basePath}/compatibilities/get_compatibility_property_values`, data);
|
|
410
410
|
}
|
|
411
411
|
catch (error) {
|
|
412
|
-
throw new Error(`Failed to get compatibility property values: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
412
|
+
throw new Error(`Failed to get compatibility property values: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
413
413
|
}
|
|
414
414
|
}
|
|
415
415
|
/**
|
|
@@ -425,7 +425,7 @@ export class MetadataApi {
|
|
|
425
425
|
return await this.client.post(`${this.basePath}/compatibilities/get_multi_compatibility_property_values`, data);
|
|
426
426
|
}
|
|
427
427
|
catch (error) {
|
|
428
|
-
throw new Error(`Failed to get multi compatibility property values: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
428
|
+
throw new Error(`Failed to get multi compatibility property values: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
429
429
|
}
|
|
430
430
|
}
|
|
431
431
|
/**
|
|
@@ -441,7 +441,7 @@ export class MetadataApi {
|
|
|
441
441
|
return await this.client.post(`${this.basePath}/compatibilities/get_product_compatibilities`, data);
|
|
442
442
|
}
|
|
443
443
|
catch (error) {
|
|
444
|
-
throw new Error(`Failed to get product compatibilities: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
444
|
+
throw new Error(`Failed to get product compatibilities: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
445
445
|
}
|
|
446
446
|
}
|
|
447
447
|
/**
|
|
@@ -457,7 +457,7 @@ export class MetadataApi {
|
|
|
457
457
|
return await this.client.get(`${this.basePath}/country/${countryCode}/sales_tax_jurisdiction`);
|
|
458
458
|
}
|
|
459
459
|
catch (error) {
|
|
460
|
-
throw new Error(`Failed to get sales tax jurisdictions: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
460
|
+
throw new Error(`Failed to get sales tax jurisdictions: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
461
461
|
}
|
|
462
462
|
}
|
|
463
463
|
/**
|
|
@@ -479,7 +479,7 @@ export class MetadataApi {
|
|
|
479
479
|
return await this.client.get(`${this.basePath}/marketplace/${marketplaceId}/get_product_compliance_policies`, params);
|
|
480
480
|
}
|
|
481
481
|
catch (error) {
|
|
482
|
-
throw new Error(`Failed to get product compliance policies: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
482
|
+
throw new Error(`Failed to get product compliance policies: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
483
483
|
}
|
|
484
484
|
}
|
|
485
485
|
}
|
|
@@ -44,7 +44,7 @@ export class MultiUserAuthStore {
|
|
|
44
44
|
* `lastUsedAt` once per TOUCH_THROTTLE_MS (default: 1 hour).
|
|
45
45
|
*/
|
|
46
46
|
sessionTouchCache = new Map();
|
|
47
|
-
static
|
|
47
|
+
static touchThrottleMs = 60 * 60 * 1_000; // 1 hour
|
|
48
48
|
stateKey(state) {
|
|
49
49
|
return `oauth_state:${state}`;
|
|
50
50
|
}
|
|
@@ -67,6 +67,12 @@ export class MultiUserAuthStore {
|
|
|
67
67
|
await this.kv.put(this.stateKey(state), record, OAUTH_STATE_TTL_S);
|
|
68
68
|
return record;
|
|
69
69
|
}
|
|
70
|
+
async getOAuthState(state) {
|
|
71
|
+
return await this.kv.get(this.stateKey(state));
|
|
72
|
+
}
|
|
73
|
+
async deleteOAuthState(state) {
|
|
74
|
+
await this.kv.delete(this.stateKey(state));
|
|
75
|
+
}
|
|
70
76
|
async consumeOAuthState(state) {
|
|
71
77
|
const key = this.stateKey(state);
|
|
72
78
|
const record = await this.kv.get(key);
|
|
@@ -122,7 +128,7 @@ export class MultiUserAuthStore {
|
|
|
122
128
|
// Skip the KV write entirely if we touched this session recently.
|
|
123
129
|
// The in-memory cache in CloudflareKVStore already keeps reads free,
|
|
124
130
|
// so the only cost we're avoiding here is the unnecessary KV PUT.
|
|
125
|
-
if (lastTouched !== undefined && now - lastTouched < MultiUserAuthStore.
|
|
131
|
+
if (lastTouched !== undefined && now - lastTouched < MultiUserAuthStore.touchThrottleMs) {
|
|
126
132
|
return;
|
|
127
133
|
}
|
|
128
134
|
const record = await this.getSession(sessionToken);
|
package/build/auth/oauth.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
|
-
import {
|
|
2
|
+
import { getOAuthTokenBaseUrl } from '../config/environment.js';
|
|
3
3
|
import { MultiUserAuthStore } from '../auth/multi-user-store.js';
|
|
4
4
|
export class EbayOAuthClient {
|
|
5
5
|
config;
|
|
@@ -8,15 +8,20 @@ export class EbayOAuthClient {
|
|
|
8
8
|
appAccessTokenExpiry = 0;
|
|
9
9
|
userTokens = null;
|
|
10
10
|
authStore = new MultiUserAuthStore();
|
|
11
|
+
authSource = null;
|
|
11
12
|
constructor(config, context) {
|
|
12
13
|
this.config = config;
|
|
13
14
|
this.context = context;
|
|
14
15
|
}
|
|
16
|
+
getTokenEndpoint() {
|
|
17
|
+
return `${getOAuthTokenBaseUrl(this.config.environment)}/identity/v1/oauth2/token`;
|
|
18
|
+
}
|
|
15
19
|
async initialize() {
|
|
16
20
|
if (this.context?.userId && this.context.environment) {
|
|
17
21
|
const stored = await this.authStore.getUserTokens(this.context.userId, this.context.environment);
|
|
18
22
|
if (stored?.tokenData) {
|
|
19
23
|
this.userTokens = stored.tokenData;
|
|
24
|
+
this.authSource = 'stored_user_tokens';
|
|
20
25
|
return;
|
|
21
26
|
}
|
|
22
27
|
}
|
|
@@ -24,7 +29,7 @@ export class EbayOAuthClient {
|
|
|
24
29
|
const envRefreshToken = process.env.EBAY_USER_REFRESH_TOKEN;
|
|
25
30
|
if (envRefreshToken) {
|
|
26
31
|
try {
|
|
27
|
-
const authUrl =
|
|
32
|
+
const authUrl = this.getTokenEndpoint();
|
|
28
33
|
const credentials = Buffer.from(`${this.config.clientId}:${this.config.clientSecret}`).toString('base64');
|
|
29
34
|
const response = await axios.post(authUrl, new URLSearchParams({
|
|
30
35
|
grant_type: 'refresh_token',
|
|
@@ -50,6 +55,7 @@ export class EbayOAuthClient {
|
|
|
50
55
|
: now + 18 * 30 * 24 * 60 * 60 * 1000,
|
|
51
56
|
scope: tokenData.scope,
|
|
52
57
|
};
|
|
58
|
+
this.authSource = 'env_refresh_token_fallback';
|
|
53
59
|
}
|
|
54
60
|
catch {
|
|
55
61
|
// If refresh fails, leave userTokens as null
|
|
@@ -99,13 +105,14 @@ export class EbayOAuthClient {
|
|
|
99
105
|
userAccessTokenExpiry: accessTokenExpiry ?? now + 7200 * 1000,
|
|
100
106
|
userRefreshTokenExpiry: refreshTokenExpiry ?? now + 18 * 30 * 24 * 60 * 60 * 1000,
|
|
101
107
|
};
|
|
108
|
+
this.authSource = 'manual_set_user_tokens';
|
|
102
109
|
await this.persistUserTokens();
|
|
103
110
|
}
|
|
104
111
|
async getOrRefreshAppAccessToken() {
|
|
105
112
|
if (this.appAccessToken && Date.now() < this.appAccessTokenExpiry) {
|
|
106
113
|
return this.appAccessToken;
|
|
107
114
|
}
|
|
108
|
-
const authUrl =
|
|
115
|
+
const authUrl = this.getTokenEndpoint();
|
|
109
116
|
const credentials = Buffer.from(`${this.config.clientId}:${this.config.clientSecret}`).toString('base64');
|
|
110
117
|
const response = await axios.post(authUrl, new URLSearchParams({
|
|
111
118
|
grant_type: 'client_credentials',
|
|
@@ -124,7 +131,7 @@ export class EbayOAuthClient {
|
|
|
124
131
|
if (!this.config.redirectUri) {
|
|
125
132
|
throw new Error('Redirect URI is required for authorization code exchange');
|
|
126
133
|
}
|
|
127
|
-
const tokenUrl =
|
|
134
|
+
const tokenUrl = this.getTokenEndpoint();
|
|
128
135
|
const credentials = Buffer.from(`${this.config.clientId}:${this.config.clientSecret}`).toString('base64');
|
|
129
136
|
try {
|
|
130
137
|
const response = await axios.post(tokenUrl, new URLSearchParams({
|
|
@@ -150,6 +157,7 @@ export class EbayOAuthClient {
|
|
|
150
157
|
userRefreshTokenExpiry: now + tokenData.refresh_token_expires_in * 1000,
|
|
151
158
|
scope: tokenData.scope,
|
|
152
159
|
};
|
|
160
|
+
this.authSource = 'authorization_code_exchange';
|
|
153
161
|
await this.persistUserTokens();
|
|
154
162
|
return tokenData;
|
|
155
163
|
}
|
|
@@ -157,10 +165,10 @@ export class EbayOAuthClient {
|
|
|
157
165
|
if (axios.isAxiosError(error) && error.response?.data) {
|
|
158
166
|
const data = error.response.data;
|
|
159
167
|
if (data.error_description) {
|
|
160
|
-
throw new Error(data.error_description);
|
|
168
|
+
throw new Error(data.error_description, { cause: error });
|
|
161
169
|
}
|
|
162
170
|
if (data.error) {
|
|
163
|
-
throw new Error(data.error);
|
|
171
|
+
throw new Error(data.error, { cause: error });
|
|
164
172
|
}
|
|
165
173
|
}
|
|
166
174
|
throw error;
|
|
@@ -170,7 +178,7 @@ export class EbayOAuthClient {
|
|
|
170
178
|
if (!this.userTokens) {
|
|
171
179
|
throw new Error('No user tokens available to refresh');
|
|
172
180
|
}
|
|
173
|
-
const authUrl =
|
|
181
|
+
const authUrl = this.getTokenEndpoint();
|
|
174
182
|
const credentials = Buffer.from(`${this.config.clientId}:${this.config.clientSecret}`).toString('base64');
|
|
175
183
|
const response = await axios.post(authUrl, new URLSearchParams({
|
|
176
184
|
grant_type: 'refresh_token',
|
|
@@ -198,6 +206,24 @@ export class EbayOAuthClient {
|
|
|
198
206
|
};
|
|
199
207
|
await this.persistUserTokens();
|
|
200
208
|
}
|
|
209
|
+
getAuthDebugInfo() {
|
|
210
|
+
return {
|
|
211
|
+
tokenEndpoint: this.getTokenEndpoint(),
|
|
212
|
+
environment: this.config.environment,
|
|
213
|
+
hasClientId: this.config.clientId.trim().length > 0,
|
|
214
|
+
hasClientSecret: this.config.clientSecret.trim().length > 0,
|
|
215
|
+
hasRefreshToken: !!this.userTokens?.userRefreshToken,
|
|
216
|
+
hasAccessToken: !!this.userTokens?.userAccessToken,
|
|
217
|
+
hasRedirectUri: !!this.config.redirectUri,
|
|
218
|
+
...(this.userTokens?.userRefreshTokenExpiry
|
|
219
|
+
? { refreshTokenExpiry: this.userTokens.userRefreshTokenExpiry }
|
|
220
|
+
: {}),
|
|
221
|
+
...(this.userTokens?.userAccessTokenExpiry
|
|
222
|
+
? { accessTokenExpiry: this.userTokens.userAccessTokenExpiry }
|
|
223
|
+
: {}),
|
|
224
|
+
...(this.authSource ? { source: this.authSource } : {}),
|
|
225
|
+
};
|
|
226
|
+
}
|
|
201
227
|
isAuthenticated() {
|
|
202
228
|
if (this.userTokens && !this.isUserAccessTokenExpired(this.userTokens)) {
|
|
203
229
|
return true;
|
|
@@ -20,7 +20,7 @@ export class TokenVerifier {
|
|
|
20
20
|
this.metadata = response.data;
|
|
21
21
|
}
|
|
22
22
|
catch (error) {
|
|
23
|
-
throw new Error(`Failed to load OAuth server metadata: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
23
|
+
throw new Error(`Failed to load OAuth server metadata: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
else {
|
|
@@ -104,7 +104,7 @@ export class TokenVerifier {
|
|
|
104
104
|
}
|
|
105
105
|
catch (error) {
|
|
106
106
|
if (axios.isAxiosError(error)) {
|
|
107
|
-
throw new Error(`Token introspection failed: ${error.response?.data?.error_description || error.message}
|
|
107
|
+
throw new Error(`Token introspection failed: ${error.response?.data?.error_description || error.message}`, { cause: error });
|
|
108
108
|
}
|
|
109
109
|
throw error;
|
|
110
110
|
}
|
|
@@ -150,7 +150,7 @@ export class TokenVerifier {
|
|
|
150
150
|
};
|
|
151
151
|
}
|
|
152
152
|
catch (error) {
|
|
153
|
-
throw new Error(`JWT verification failed: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
153
|
+
throw new Error(`JWT verification failed: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
/**
|
|
@@ -289,9 +289,19 @@ export function getEbayConfig(environmentOverride) {
|
|
|
289
289
|
appAccessToken: process.env.EBAY_APP_ACCESS_TOKEN ?? '',
|
|
290
290
|
};
|
|
291
291
|
}
|
|
292
|
+
export function getValidationRunnerUserId(environment) {
|
|
293
|
+
const envSpecific = environment === 'production'
|
|
294
|
+
? process.env.VALIDATION_RUNNER_USER_ID_PRODUCTION
|
|
295
|
+
: process.env.VALIDATION_RUNNER_USER_ID_SANDBOX;
|
|
296
|
+
const resolved = (envSpecific ?? process.env.VALIDATION_RUNNER_USER_ID ?? '').trim();
|
|
297
|
+
return resolved || null;
|
|
298
|
+
}
|
|
292
299
|
export function getBaseUrl(environment) {
|
|
293
300
|
return environment === 'production' ? 'https://api.ebay.com' : 'https://api.sandbox.ebay.com';
|
|
294
301
|
}
|
|
302
|
+
export function getOAuthTokenBaseUrl(environment) {
|
|
303
|
+
return environment === 'production' ? 'https://api.ebay.com' : 'https://api.sandbox.ebay.com';
|
|
304
|
+
}
|
|
295
305
|
export function getIdentityBaseUrl(environment) {
|
|
296
306
|
return environment === 'production' ? 'https://apiz.ebay.com' : 'https://apiz.sandbox.ebay.com';
|
|
297
307
|
}
|
|
@@ -11,7 +11,7 @@ function isHostedEnvironment() {
|
|
|
11
11
|
function main() {
|
|
12
12
|
const args = process.argv.slice(2);
|
|
13
13
|
if (args.length === 0) {
|
|
14
|
-
throw new Error('Usage: tsx src/scripts/
|
|
14
|
+
throw new Error('Usage: tsx src/scripts/env-check.ts <command> [args...]');
|
|
15
15
|
}
|
|
16
16
|
const hosted = isHostedEnvironment();
|
|
17
17
|
const [command, ...commandArgs] = args;
|