ebay-mcp 1.18.0 → 1.18.2
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/README.md +24 -35
- package/build/api/account-management/accountV2.js +22 -22
- package/build/api/account-management/finances.js +10 -10
- package/build/api/analytics-and-report/analytics.js +1 -1
- package/build/api/{client.js → client/ebayApiClient.js} +37 -41
- package/build/api/{clientTrading.js → client/tradingApiClient.js} +22 -22
- package/build/api/communication/feedback.js +21 -21
- package/build/api/communication/message.js +23 -23
- package/build/api/communication/negotiation.js +7 -7
- package/build/api/communication/notification.js +52 -52
- package/build/api/developer/developer.js +3 -3
- package/build/api/{index.js → ebaySellerApi.js} +4 -4
- package/build/api/listing-management/feedReportTasks.js +6 -6
- package/build/api/listing-management/feedRequest.js +6 -6
- package/build/api/listing-management/feedSchedules.js +4 -4
- package/build/api/listing-management/feedTasks.js +2 -2
- package/build/api/listing-management/items.js +22 -22
- package/build/api/listing-management/locations.js +4 -4
- package/build/api/listing-management/media.js +14 -14
- package/build/api/listing-management/mediaAttach.js +14 -14
- package/build/api/listing-management/mediaResources.js +15 -13
- package/build/api/listing-management/offerFormat.js +1 -1
- package/build/api/listing-management/offers.js +23 -23
- package/build/api/listing-management/stores.js +9 -9
- package/build/api/listing-metadata/metadata.js +10 -10
- package/build/api/marketing-and-promotions/ads.js +34 -34
- package/build/api/marketing-and-promotions/campaigns.js +19 -19
- package/build/api/marketing-and-promotions/promotions.js +22 -22
- package/build/api/marketing-and-promotions/reports.js +7 -7
- package/build/api/order-management/dispute.js +11 -9
- package/build/api/order-management/fulfillment.js +4 -4
- package/build/api/order-management/logistics.js +7 -7
- package/build/api/other/browseMappers.js +15 -13
- package/build/api/other/browseValidators.js +4 -4
- package/build/api/other/edelivery.js +19 -19
- package/build/api/other/finding.js +13 -13
- package/build/api/other/translation.js +2 -2
- package/build/api/other/vero.js +2 -2
- package/build/api/shared/download.js +7 -7
- package/build/api/shared/request.js +28 -19
- package/build/api/trading/listingFormat.js +37 -30
- package/build/api/trading/trading.js +33 -33
- package/build/auth/credentialSession.js +5 -5
- package/build/auth/oauth.js +3 -3
- package/build/auth/oauthHelper.js +24 -24
- package/build/auth/oauthMetadata.js +4 -4
- package/build/auth/oauthMiddleware.js +16 -16
- package/build/auth/scopeUtils.js +2 -2
- package/build/auth/tokenVerifier.js +23 -23
- package/build/config/environment.js +4 -45
- package/build/config/oauthScopes.js +132 -0
- package/build/index.js +5 -5
- package/build/mcp/httpTransport.js +32 -20
- package/build/mcp/runtime.js +12 -12
- package/build/mcp/toolGating.js +6 -12
- package/build/mcp/uiBridge.js +3 -3
- package/build/schemas/account-management/account.js +2 -52
- package/build/schemas/account-management/accountV2.js +2 -2
- package/build/schemas/account-management/finances.js +1 -1
- package/build/schemas/analytics/analytics.js +2 -48
- package/build/schemas/communication/messages.js +2 -46
- package/build/schemas/developer/developer.js +1 -27
- package/build/schemas/fulfillment/logistics.js +1 -1
- package/build/schemas/fulfillment/orders.js +2 -47
- package/build/schemas/inventory-management/feed.js +1 -1
- package/build/schemas/inventory-management/inventory.js +2 -50
- package/build/schemas/inventory-management/media.js +2 -2
- package/build/schemas/inventory-management/mediaDocuments.js +1 -1
- package/build/schemas/inventory-management/stores.js +1 -1
- package/build/schemas/marketing/ads.js +2 -2
- package/build/schemas/marketing/campaigns.js +2 -2
- package/build/schemas/marketing/common.js +2 -2
- package/build/schemas/marketing/marketing.js +0 -1
- package/build/schemas/marketing/promotions.js +2 -2
- package/build/schemas/marketing/reports.js +2 -2
- package/build/schemas/metadata/metadata.js +2 -90
- package/build/schemas/metadata/shipping.js +1 -1
- package/build/schemas/other/browse.js +2 -2
- package/build/schemas/other/finding.js +2 -2
- package/build/schemas/other/otherApis.js +2 -114
- package/build/schemas/taxonomy/categoryTree.js +1 -1
- package/build/schemas/taxonomy/charity.js +1 -1
- package/build/schemas/taxonomy/taxonomy.js +2 -69
- package/build/scripts/autoSetup.js +3 -3
- package/build/scripts/{buildUi.js → buildMcpApps.js} +13 -13
- package/build/scripts/devSync.js +19 -68
- package/build/scripts/diagnostics.js +15 -16
- package/build/scripts/interactiveSetup.js +25 -25
- package/build/scripts/scopeHelper.js +2 -2
- package/build/scripts/securityChecker.js +20 -20
- package/build/scripts/setup.js +76 -76
- package/build/scripts/setupShared.js +5 -30
- package/build/scripts/setupValidator.js +9 -9
- package/build/scripts/setupWizard.js +23 -23
- package/build/scripts/skills.js +14 -17
- package/build/scripts/specRefs.js +1 -1
- package/build/scripts/specSources.js +144 -0
- package/build/serverHttp.js +4 -7
- package/build/skills/content.js +13 -13
- package/build/skills/install.js +9 -9
- package/build/skills/render.js +2 -2
- package/build/tools/categories/communication.js +1 -1
- package/build/tools/categories/connector.js +19 -16
- package/build/tools/categories/fulfillment.js +4 -4
- package/build/tools/categories/inventory.js +1 -1
- package/build/tools/categories/metadata.js +1 -1
- package/build/tools/categories/taxonomy.js +1 -1
- package/build/tools/categories/tokenManagement.js +8 -8
- package/build/tools/contracts.js +2 -2
- package/build/tools/defineTool.js +27 -12
- package/build/tools/registry.js +2 -2
- package/build/tools/schemas.js +2 -2
- package/build/tools/ui/mapHelpers.js +12 -12
- package/build/tools/ui/maps.js +101 -97
- package/build/tools/ui/viewModels.js +2 -2
- package/build/utils/apiStatusFeed.js +12 -12
- package/build/utils/communication/feedback.js +3 -3
- package/build/utils/communication/message.js +3 -3
- package/build/utils/communication/negotiation.js +3 -3
- package/build/utils/communication/notification.js +3 -3
- package/build/utils/entryModule.js +33 -0
- package/build/utils/envFile.js +47 -0
- package/build/utils/envParser.js +5 -5
- package/build/utils/errors.js +4 -4
- package/build/utils/http.js +38 -38
- package/build/utils/localFeedFiles.js +3 -3
- package/build/utils/logRedaction.js +21 -0
- package/build/utils/logger.js +49 -35
- package/build/utils/other/compliance.js +3 -3
- package/build/utils/other/identity.js +3 -3
- package/build/utils/other/translation.js +3 -3
- package/build/utils/other/vero.js +3 -3
- package/build/utils/schemaHelpers.js +2 -2
- package/build/utils/tokenUtils.js +2 -2
- package/build/utils/trading/trading.js +1 -1
- package/build/utils/version.js +1 -1
- package/build/utils/zodIssues.js +14 -0
- package/package.json +8 -11
- package/README.de.md +0 -426
- package/README.es.md +0 -426
- package/README.fr.md +0 -426
- package/README.ja.md +0 -426
- package/README.ko.md +0 -426
- package/README.pt-BR.md +0 -426
- package/README.ru.md +0 -426
- package/README.zh-CN.md +0 -426
- package/build/schemas/index.js +0 -76
- package/build/schemas/marketing/jsonSchemas.js +0 -118
- package/build/scripts/downloadSpecs.js +0 -117
- package/build/scripts/updateApiStatusDoc.js +0 -71
- package/build/utils/effectSchema.js +0 -203
- package/build/utils/effectSchemaAdapter.js +0 -121
- package/build/utils/effectSchemaChainMethods.js +0 -146
- package/build/utils/effectSchemaRefinements.js +0 -104
- package/build/utils/effectSchemaStringMethods.js +0 -63
- package/build/utils/effectSchemaTypes.js +0 -47
- package/docs/auth/production_scopes.json +0 -111
- package/docs/auth/sandbox_scopes.json +0 -142
- /package/build/api/{clientRequestError.js → client/ebayClientRequestError.js} +0 -0
- /package/build/api/{rateLimitTracker.js → client/rateLimitTracker.js} +0 -0
- /package/build/api/{clientTradingError.js → client/tradingApiFailure.js} +0 -0
|
@@ -11,7 +11,7 @@ export const createInventoryItemsMethods = (client) => ({
|
|
|
11
11
|
*
|
|
12
12
|
* @example
|
|
13
13
|
* ```ts
|
|
14
|
-
* const
|
|
14
|
+
* const inventoryPage = await Effect.runPromise(inventoryApi.getInventoryItems({ limit: 25 }));
|
|
15
15
|
* ```
|
|
16
16
|
*
|
|
17
17
|
* @see https://developer.ebay.com/api-docs/sell/inventory/resources/inventory_item/methods/getInventoryItems
|
|
@@ -37,7 +37,7 @@ export const createInventoryItemsMethods = (client) => ({
|
|
|
37
37
|
*
|
|
38
38
|
* @example
|
|
39
39
|
* ```ts
|
|
40
|
-
* const
|
|
40
|
+
* const inventoryItem = await Effect.runPromise(inventoryApi.getInventoryItem({ sku: 'SKU-1' }));
|
|
41
41
|
* ```
|
|
42
42
|
*
|
|
43
43
|
* @see https://developer.ebay.com/api-docs/sell/inventory/resources/inventory_item/methods/getInventoryItem
|
|
@@ -70,11 +70,11 @@ export const createInventoryItemsMethods = (client) => ({
|
|
|
70
70
|
return Effect.gen(function* () {
|
|
71
71
|
const validatedInput = yield* requireObjectEffect(input, 'input');
|
|
72
72
|
const sku = yield* requireStringEffect(validatedInput.sku, 'sku');
|
|
73
|
-
const
|
|
73
|
+
const inventoryItem = yield* requireObjectEffect(validatedInput.body, 'body');
|
|
74
74
|
const config = validatedInput.contentLanguage === undefined
|
|
75
75
|
? undefined
|
|
76
76
|
: { headers: { 'Content-Language': validatedInput.contentLanguage } };
|
|
77
|
-
return yield* requestPutEffect(client, `${basePath}/inventory_item/${sku}`,
|
|
77
|
+
return yield* requestPutEffect(client, `${basePath}/inventory_item/${sku}`, inventoryItem, config);
|
|
78
78
|
});
|
|
79
79
|
},
|
|
80
80
|
/**
|
|
@@ -106,7 +106,7 @@ export const createInventoryItemsMethods = (client) => ({
|
|
|
106
106
|
*
|
|
107
107
|
* @example
|
|
108
108
|
* ```ts
|
|
109
|
-
* const
|
|
109
|
+
* const inventoryItemResults = await Effect.runPromise(
|
|
110
110
|
* inventoryApi.bulkCreateOrReplaceInventoryItem({ body: { requests: [] } }),
|
|
111
111
|
* );
|
|
112
112
|
* ```
|
|
@@ -117,8 +117,8 @@ export const createInventoryItemsMethods = (client) => ({
|
|
|
117
117
|
const path = `${INVENTORY_BASE_PATH}/bulk_create_or_replace_inventory_item`;
|
|
118
118
|
return Effect.gen(function* () {
|
|
119
119
|
const validatedInput = yield* requireObjectEffect(input, 'input');
|
|
120
|
-
const
|
|
121
|
-
return yield* requestPostEffect(client, path,
|
|
120
|
+
const bulkInventoryItemRequest = yield* requireObjectEffect(validatedInput.body, 'body');
|
|
121
|
+
return yield* requestPostEffect(client, path, bulkInventoryItemRequest);
|
|
122
122
|
});
|
|
123
123
|
},
|
|
124
124
|
/**
|
|
@@ -129,7 +129,7 @@ export const createInventoryItemsMethods = (client) => ({
|
|
|
129
129
|
*
|
|
130
130
|
* @example
|
|
131
131
|
* ```ts
|
|
132
|
-
* const
|
|
132
|
+
* const inventoryItems = await Effect.runPromise(
|
|
133
133
|
* inventoryApi.bulkGetInventoryItem({ body: { requests: [{ sku: 'SKU-1' }] } }),
|
|
134
134
|
* );
|
|
135
135
|
* ```
|
|
@@ -140,8 +140,8 @@ export const createInventoryItemsMethods = (client) => ({
|
|
|
140
140
|
const path = `${INVENTORY_BASE_PATH}/bulk_get_inventory_item`;
|
|
141
141
|
return Effect.gen(function* () {
|
|
142
142
|
const validatedInput = yield* requireObjectEffect(input, 'input');
|
|
143
|
-
const
|
|
144
|
-
return yield* requestPostEffect(client, path,
|
|
143
|
+
const bulkGetInventoryItemRequest = yield* requireObjectEffect(validatedInput.body, 'body');
|
|
144
|
+
return yield* requestPostEffect(client, path, bulkGetInventoryItemRequest);
|
|
145
145
|
});
|
|
146
146
|
},
|
|
147
147
|
/**
|
|
@@ -152,7 +152,7 @@ export const createInventoryItemsMethods = (client) => ({
|
|
|
152
152
|
*
|
|
153
153
|
* @example
|
|
154
154
|
* ```ts
|
|
155
|
-
* const
|
|
155
|
+
* const priceQuantityResults = await Effect.runPromise(
|
|
156
156
|
* inventoryApi.bulkUpdatePriceQuantity({ body: { requests: [] } }),
|
|
157
157
|
* );
|
|
158
158
|
* ```
|
|
@@ -163,8 +163,8 @@ export const createInventoryItemsMethods = (client) => ({
|
|
|
163
163
|
const path = `${INVENTORY_BASE_PATH}/bulk_update_price_quantity`;
|
|
164
164
|
return Effect.gen(function* () {
|
|
165
165
|
const validatedInput = yield* requireObjectEffect(input, 'input');
|
|
166
|
-
const
|
|
167
|
-
return yield* requestPostEffect(client, path,
|
|
166
|
+
const bulkPriceQuantityRequest = yield* requireObjectEffect(validatedInput.body, 'body');
|
|
167
|
+
return yield* requestPostEffect(client, path, bulkPriceQuantityRequest);
|
|
168
168
|
});
|
|
169
169
|
},
|
|
170
170
|
/**
|
|
@@ -210,8 +210,8 @@ export const createInventoryItemsMethods = (client) => ({
|
|
|
210
210
|
return Effect.gen(function* () {
|
|
211
211
|
const validatedInput = yield* requireObjectEffect(input, 'input');
|
|
212
212
|
const sku = yield* requireStringEffect(validatedInput.sku, 'sku');
|
|
213
|
-
const
|
|
214
|
-
return yield* requestPutEffect(client, `${basePath}/inventory_item/${sku}/product_compatibility`,
|
|
213
|
+
const productCompatibility = yield* requireObjectEffect(validatedInput.body, 'body');
|
|
214
|
+
return yield* requestPutEffect(client, `${basePath}/inventory_item/${sku}/product_compatibility`, productCompatibility);
|
|
215
215
|
});
|
|
216
216
|
},
|
|
217
217
|
/**
|
|
@@ -281,8 +281,8 @@ export const createInventoryItemsMethods = (client) => ({
|
|
|
281
281
|
return Effect.gen(function* () {
|
|
282
282
|
const validatedInput = yield* requireObjectEffect(input, 'input');
|
|
283
283
|
const inventoryItemGroupKey = yield* requireStringEffect(validatedInput.inventoryItemGroupKey, 'inventoryItemGroupKey');
|
|
284
|
-
const
|
|
285
|
-
return yield* requestPutEffect(client, `${basePath}/inventory_item_group/${inventoryItemGroupKey}`,
|
|
284
|
+
const inventoryItemGroup = yield* requireObjectEffect(validatedInput.body, 'body');
|
|
285
|
+
return yield* requestPutEffect(client, `${basePath}/inventory_item_group/${inventoryItemGroupKey}`, inventoryItemGroup);
|
|
286
286
|
});
|
|
287
287
|
},
|
|
288
288
|
/**
|
|
@@ -316,7 +316,7 @@ export const createInventoryItemsMethods = (client) => ({
|
|
|
316
316
|
*
|
|
317
317
|
* @example
|
|
318
318
|
* ```ts
|
|
319
|
-
* const
|
|
319
|
+
* const migratedListings = await Effect.runPromise(
|
|
320
320
|
* inventoryApi.bulkMigrateListing({ body: { requests: [] } }),
|
|
321
321
|
* );
|
|
322
322
|
* ```
|
|
@@ -327,8 +327,8 @@ export const createInventoryItemsMethods = (client) => ({
|
|
|
327
327
|
const path = `${INVENTORY_BASE_PATH}/bulk_migrate_listing`;
|
|
328
328
|
return Effect.gen(function* () {
|
|
329
329
|
const validatedInput = yield* requireObjectEffect(input, 'input');
|
|
330
|
-
const
|
|
331
|
-
return yield* requestPostEffect(client, path,
|
|
330
|
+
const bulkMigrateListingRequest = yield* requireObjectEffect(validatedInput.body, 'body');
|
|
331
|
+
return yield* requestPostEffect(client, path, bulkMigrateListingRequest);
|
|
332
332
|
});
|
|
333
333
|
},
|
|
334
334
|
/**
|
|
@@ -380,8 +380,8 @@ export const createInventoryItemsMethods = (client) => ({
|
|
|
380
380
|
const validatedInput = yield* requireObjectEffect(input, 'input');
|
|
381
381
|
const listingId = yield* requireStringEffect(validatedInput.listingId, 'listingId');
|
|
382
382
|
const sku = yield* requireStringEffect(validatedInput.sku, 'sku');
|
|
383
|
-
const
|
|
384
|
-
return yield* requestPutEffect(client, `${basePath}/listing/${listingId}/sku/${sku}/locations`,
|
|
383
|
+
const locationMapping = yield* requireObjectEffect(validatedInput.body, 'body');
|
|
384
|
+
return yield* requestPutEffect(client, `${basePath}/listing/${listingId}/sku/${sku}/locations`, locationMapping);
|
|
385
385
|
});
|
|
386
386
|
},
|
|
387
387
|
/**
|
|
@@ -46,8 +46,8 @@ export const createInventoryLocationsMethods = (client) => ({
|
|
|
46
46
|
return Effect.gen(function* () {
|
|
47
47
|
const validatedInput = yield* requireObjectEffect(input, 'input');
|
|
48
48
|
const merchantLocationKey = yield* requireStringEffect(validatedInput.merchantLocationKey, 'merchantLocationKey');
|
|
49
|
-
const
|
|
50
|
-
return yield* requestPostEffect(client, `${basePath}/location/${merchantLocationKey}`,
|
|
49
|
+
const inventoryLocation = yield* requireObjectEffect(validatedInput.body, 'body');
|
|
50
|
+
return yield* requestPostEffect(client, `${basePath}/location/${merchantLocationKey}`, inventoryLocation);
|
|
51
51
|
});
|
|
52
52
|
},
|
|
53
53
|
/**
|
|
@@ -165,8 +165,8 @@ export const createInventoryLocationsMethods = (client) => ({
|
|
|
165
165
|
return Effect.gen(function* () {
|
|
166
166
|
const validatedInput = yield* requireObjectEffect(input, 'input');
|
|
167
167
|
const merchantLocationKey = yield* requireStringEffect(validatedInput.merchantLocationKey, 'merchantLocationKey');
|
|
168
|
-
const
|
|
169
|
-
return yield* requestPostEffect(client, `${basePath}/location/${merchantLocationKey}/update_location_details`,
|
|
168
|
+
const inventoryLocationUpdate = yield* requireObjectEffect(validatedInput.body, 'body');
|
|
169
|
+
return yield* requestPostEffect(client, `${basePath}/location/${merchantLocationKey}/update_location_details`, inventoryLocationUpdate);
|
|
170
170
|
});
|
|
171
171
|
},
|
|
172
172
|
});
|
|
@@ -33,23 +33,23 @@ const videoStatusFinal = (video) => video.status !== undefined && TERMINAL_VIDEO
|
|
|
33
33
|
* standing still while status requests kept going, so the boundary is checked
|
|
34
34
|
* before the first poll rather than inside the loop.
|
|
35
35
|
*
|
|
36
|
-
* @param
|
|
36
|
+
* @param durationMs - Caller-supplied duration in milliseconds, or undefined.
|
|
37
37
|
* @param fallback - Duration used when the caller supplied none.
|
|
38
38
|
* @param name - Parameter name used in the validation message.
|
|
39
39
|
* @param minimum - Smallest accepted value.
|
|
40
40
|
* @returns An Effect with the duration to use, or a tagged input error.
|
|
41
41
|
*/
|
|
42
|
-
const requireDurationMs = (
|
|
43
|
-
if (
|
|
42
|
+
const requireDurationMs = (durationMs, fallback, name, minimum) => {
|
|
43
|
+
if (durationMs === undefined) {
|
|
44
44
|
return Effect.succeed(fallback);
|
|
45
45
|
}
|
|
46
|
-
if (!Number.isFinite(
|
|
46
|
+
if (!Number.isFinite(durationMs) || durationMs < minimum) {
|
|
47
47
|
return Effect.fail(new EndpointInputError({
|
|
48
48
|
parameter: name,
|
|
49
49
|
message: `${name} must be a finite number of milliseconds of at least ${minimum} when provided`,
|
|
50
50
|
}));
|
|
51
51
|
}
|
|
52
|
-
return Effect.succeed(
|
|
52
|
+
return Effect.succeed(durationMs);
|
|
53
53
|
};
|
|
54
54
|
/**
|
|
55
55
|
* Media API client. Image and video uploads go to eBay's `apim` host and return
|
|
@@ -120,14 +120,14 @@ export class MediaApi {
|
|
|
120
120
|
const form = new FormData();
|
|
121
121
|
// Copy into a fresh ArrayBuffer-backed view: Blob rejects Node's ArrayBufferLike-typed views.
|
|
122
122
|
form.append('image', new Blob([new Uint8Array(upload.bytes)], { type: upload.mimeType }), fileName);
|
|
123
|
-
const
|
|
123
|
+
const imageResponse = yield* Effect.tryPromise({
|
|
124
124
|
try: () => client.postForResponse(url, form, {
|
|
125
125
|
absolute: true,
|
|
126
126
|
timeoutMs: UPLOAD_TIMEOUT_MS,
|
|
127
127
|
}),
|
|
128
128
|
catch: apiFailure('POST', path),
|
|
129
129
|
});
|
|
130
|
-
const imageUrl =
|
|
130
|
+
const imageUrl = imageResponse.data?.imageUrl;
|
|
131
131
|
if (!imageUrl) {
|
|
132
132
|
return yield* Effect.fail(new EbayApiError({
|
|
133
133
|
method: 'POST',
|
|
@@ -137,9 +137,9 @@ export class MediaApi {
|
|
|
137
137
|
}
|
|
138
138
|
return {
|
|
139
139
|
source: upload.source,
|
|
140
|
-
imageId: idFromLocation(
|
|
140
|
+
imageId: idFromLocation(imageResponse.headers.location),
|
|
141
141
|
imageUrl,
|
|
142
|
-
expirationDate:
|
|
142
|
+
expirationDate: imageResponse.data?.expirationDate,
|
|
143
143
|
};
|
|
144
144
|
});
|
|
145
145
|
};
|
|
@@ -166,7 +166,7 @@ export class MediaApi {
|
|
|
166
166
|
index,
|
|
167
167
|
uploaded: [...uploaded],
|
|
168
168
|
cause,
|
|
169
|
-
message: `upload of ${file.source} (file ${index + 1} of ${files.length}) failed: ${getErrorMessage(cause)}${uploaded.length > 0 ? `; already uploaded: ${uploaded.map((
|
|
169
|
+
message: `upload of ${file.source} (file ${index + 1} of ${files.length}) failed: ${getErrorMessage(cause)}${uploaded.length > 0 ? `; already uploaded: ${uploaded.map((uploadedImage) => uploadedImage.imageUrl).join(', ')}` : ''}`,
|
|
170
170
|
})));
|
|
171
171
|
uploaded.push(image);
|
|
172
172
|
}
|
|
@@ -218,17 +218,17 @@ export class MediaApi {
|
|
|
218
218
|
return Effect.gen(function* () {
|
|
219
219
|
const validated = yield* requireObjectEffect(input, 'input');
|
|
220
220
|
const title = yield* requireStringEffect(validated.title, 'title');
|
|
221
|
-
const
|
|
221
|
+
const videoRequest = {
|
|
222
222
|
title,
|
|
223
223
|
size: validated.size,
|
|
224
224
|
description: validated.description,
|
|
225
225
|
classification: ['ITEM'],
|
|
226
226
|
};
|
|
227
|
-
const
|
|
228
|
-
try: () => client.postForResponse(url,
|
|
227
|
+
const videoResponse = yield* Effect.tryPromise({
|
|
228
|
+
try: () => client.postForResponse(url, videoRequest, { absolute: true }),
|
|
229
229
|
catch: apiFailure('POST', path),
|
|
230
230
|
});
|
|
231
|
-
const videoId = idFromLocation(
|
|
231
|
+
const videoId = idFromLocation(videoResponse.headers.location);
|
|
232
232
|
if (!videoId) {
|
|
233
233
|
return yield* Effect.fail(new EbayApiError({
|
|
234
234
|
method: 'POST',
|
|
@@ -6,13 +6,13 @@ export class MediaAttachError extends Data.TaggedError('MediaAttachError') {
|
|
|
6
6
|
}
|
|
7
7
|
const dedupe = (values) => [...new Set(values)];
|
|
8
8
|
/** Keeps only the fields createOrReplaceInventoryItem accepts (drops sku/group metadata). */
|
|
9
|
-
const toInventoryItemBody = (
|
|
10
|
-
availability:
|
|
11
|
-
condition:
|
|
12
|
-
conditionDescription:
|
|
13
|
-
conditionDescriptors:
|
|
14
|
-
packageWeightAndSize:
|
|
15
|
-
product:
|
|
9
|
+
const toInventoryItemBody = (inventoryItem) => ({
|
|
10
|
+
availability: inventoryItem.availability,
|
|
11
|
+
condition: inventoryItem.condition,
|
|
12
|
+
conditionDescription: inventoryItem.conditionDescription,
|
|
13
|
+
conditionDescriptors: inventoryItem.conditionDescriptors,
|
|
14
|
+
packageWeightAndSize: inventoryItem.packageWeightAndSize,
|
|
15
|
+
product: inventoryItem.product,
|
|
16
16
|
});
|
|
17
17
|
/** `Content-Language` value for an inventory item locale such as `en_US`. */
|
|
18
18
|
const contentLanguageOf = (locale) => locale?.replace('_', '-');
|
|
@@ -68,9 +68,9 @@ const failedOutcome = (file, kind, cause) => ({
|
|
|
68
68
|
status: 'failed',
|
|
69
69
|
error: getErrorMessage(cause),
|
|
70
70
|
});
|
|
71
|
-
const attachFailure = (summary,
|
|
72
|
-
message: `${summary}. Results: ${JSON.stringify({ images:
|
|
73
|
-
result,
|
|
71
|
+
const attachFailure = (summary, attachResult) => new MediaAttachError({
|
|
72
|
+
message: `${summary}. Results: ${JSON.stringify({ images: attachResult.images, videos: attachResult.videos })}`,
|
|
73
|
+
result: attachResult,
|
|
74
74
|
});
|
|
75
75
|
/** Uploads every file, turning each failure into a `failed` outcome instead of aborting. */
|
|
76
76
|
const uploadAll = (media, input) => Effect.gen(function* () {
|
|
@@ -117,7 +117,7 @@ export const createMediaAttachMethods = (items, media) => ({
|
|
|
117
117
|
const { images, videos } = yield* uploadAll(media, input);
|
|
118
118
|
const failed = [...images, ...videos].filter((outcome) => outcome.status === 'failed');
|
|
119
119
|
const uploaded = uploadedMedia(images, videos);
|
|
120
|
-
const
|
|
120
|
+
const attachResult = {
|
|
121
121
|
sku: input.sku,
|
|
122
122
|
updated: false,
|
|
123
123
|
images,
|
|
@@ -125,10 +125,10 @@ export const createMediaAttachMethods = (items, media) => ({
|
|
|
125
125
|
...mergeMedia(snapshot.product ?? {}, input, uploaded),
|
|
126
126
|
};
|
|
127
127
|
if (failed.length > 0 && !input.allowPartial) {
|
|
128
|
-
return yield* Effect.fail(attachFailure(`${failed.length} of ${total} uploads failed; inventory item ${input.sku} was not updated (pass allowPartial: true to attach the successful ones)`,
|
|
128
|
+
return yield* Effect.fail(attachFailure(`${failed.length} of ${total} uploads failed; inventory item ${input.sku} was not updated (pass allowPartial: true to attach the successful ones)`, attachResult));
|
|
129
129
|
}
|
|
130
130
|
if (uploaded.imageUrls.length + uploaded.videoIds.length === 0) {
|
|
131
|
-
return yield* Effect.fail(attachFailure(`no media was uploaded successfully; inventory item ${input.sku} was not updated`,
|
|
131
|
+
return yield* Effect.fail(attachFailure(`no media was uploaded successfully; inventory item ${input.sku} was not updated`, attachResult));
|
|
132
132
|
}
|
|
133
133
|
// Re-read right before the complete-replacement PUT: the uploads can take
|
|
134
134
|
// minutes, and the earlier snapshot must not overwrite edits made meanwhile.
|
|
@@ -140,6 +140,6 @@ export const createMediaAttachMethods = (items, media) => ({
|
|
|
140
140
|
contentLanguage: contentLanguageOf(latest.locale),
|
|
141
141
|
body: { ...toInventoryItemBody(latest), product: { ...product, ...merged } },
|
|
142
142
|
});
|
|
143
|
-
return { ...
|
|
143
|
+
return { ...attachResult, ...merged, updated: true };
|
|
144
144
|
}),
|
|
145
145
|
});
|
|
@@ -32,16 +32,16 @@ export const createMediaResourceMethods = (client) => {
|
|
|
32
32
|
* @see https://developer.ebay.com/api-docs/commerce/media/resources/image/methods/createImageFromUrl
|
|
33
33
|
*/
|
|
34
34
|
const createImageFromUrl = (input) => Effect.gen(function* () {
|
|
35
|
-
const
|
|
35
|
+
const imageSource = yield* decodeEndpointInputEffect(createImageFromUrlInputSchema, input);
|
|
36
36
|
const path = '/image/create_image_from_url';
|
|
37
|
-
const
|
|
38
|
-
try: () => client.postForResponse(url(path),
|
|
37
|
+
const imageResponse = yield* Effect.tryPromise({
|
|
38
|
+
try: () => client.postForResponse(url(path), imageSource, {
|
|
39
39
|
absolute: true,
|
|
40
40
|
}),
|
|
41
41
|
catch: failure('POST', path),
|
|
42
42
|
});
|
|
43
|
-
const resource = yield* locatedResourceId(
|
|
44
|
-
return { imageId: resource.id, location: resource.location, image:
|
|
43
|
+
const resource = yield* locatedResourceId(imageResponse.headers.location, `${BASE_PATH}/image`);
|
|
44
|
+
return { imageId: resource.id, location: resource.location, image: imageResponse.data };
|
|
45
45
|
});
|
|
46
46
|
/**
|
|
47
47
|
* Stages a listing document for subsequent upload.
|
|
@@ -51,9 +51,11 @@ export const createMediaResourceMethods = (client) => {
|
|
|
51
51
|
* @see https://developer.ebay.com/api-docs/commerce/media/resources/document/methods/createDocument
|
|
52
52
|
*/
|
|
53
53
|
const createDocument = (input) => Effect.gen(function* () {
|
|
54
|
-
const
|
|
54
|
+
const documentRequest = yield* decodeEndpointInputEffect(createDocumentInputSchema, input);
|
|
55
55
|
return yield* Effect.tryPromise({
|
|
56
|
-
try: () => client.post(url('/document'),
|
|
56
|
+
try: () => client.post(url('/document'), documentRequest, {
|
|
57
|
+
absolute: true,
|
|
58
|
+
}),
|
|
57
59
|
catch: failure('POST', '/document'),
|
|
58
60
|
});
|
|
59
61
|
});
|
|
@@ -65,10 +67,10 @@ export const createMediaResourceMethods = (client) => {
|
|
|
65
67
|
* @see https://developer.ebay.com/api-docs/commerce/media/resources/document/methods/createDocumentFromUrl
|
|
66
68
|
*/
|
|
67
69
|
const createDocumentFromUrl = (input) => Effect.gen(function* () {
|
|
68
|
-
const
|
|
70
|
+
const documentRequest = yield* decodeEndpointInputEffect(createDocumentFromUrlInputSchema, input);
|
|
69
71
|
const path = '/document/create_document_from_url';
|
|
70
72
|
return yield* Effect.tryPromise({
|
|
71
|
-
try: () => client.post(url(path),
|
|
73
|
+
try: () => client.post(url(path), documentRequest, { absolute: true }),
|
|
72
74
|
catch: failure('POST', path),
|
|
73
75
|
});
|
|
74
76
|
});
|
|
@@ -115,18 +117,18 @@ export const createMediaResourceMethods = (client) => {
|
|
|
115
117
|
const uploadPostOrderDocument = (input) => Effect.gen(function* () {
|
|
116
118
|
const metadata = yield* decodeEndpointInputEffect(postOrderDocumentMetadataSchema, input);
|
|
117
119
|
const form = uploadForm(input.file);
|
|
118
|
-
for (const [
|
|
119
|
-
form.append(
|
|
120
|
+
for (const [fieldName, fieldValue] of Object.entries(metadata)) {
|
|
121
|
+
form.append(fieldName, fieldValue);
|
|
120
122
|
}
|
|
121
123
|
const path = '/post_order/document';
|
|
122
|
-
const
|
|
124
|
+
const uploadResponse = yield* Effect.tryPromise({
|
|
123
125
|
try: () => client.postForResponse(url(path, true), form, {
|
|
124
126
|
absolute: true,
|
|
125
127
|
timeoutMs: UPLOAD_TIMEOUT_MS,
|
|
126
128
|
}),
|
|
127
129
|
catch: failure('POST', path),
|
|
128
130
|
});
|
|
129
|
-
const resource = yield* locatedResourceId(
|
|
131
|
+
const resource = yield* locatedResourceId(uploadResponse.headers.location, `${BASE_PATH}${path}`);
|
|
130
132
|
return { documentId: resource.id, location: resource.location };
|
|
131
133
|
});
|
|
132
134
|
/**
|
|
@@ -102,7 +102,7 @@ export const findOfferFormatViolation = (offer, parameter) => {
|
|
|
102
102
|
*
|
|
103
103
|
* @example
|
|
104
104
|
* ```ts
|
|
105
|
-
* yield* validateOfferFormatEffect(
|
|
105
|
+
* yield* validateOfferFormatEffect(offerDetails, 'body');
|
|
106
106
|
* ```
|
|
107
107
|
*/
|
|
108
108
|
export const validateOfferFormatEffect = (offer, parameter) => {
|
|
@@ -36,7 +36,7 @@ export const createInventoryOffersMethods = (client) => ({
|
|
|
36
36
|
*
|
|
37
37
|
* @example
|
|
38
38
|
* ```ts
|
|
39
|
-
* const
|
|
39
|
+
* const createdOffers = await Effect.runPromise(inventoryApi.bulkCreateOffer({ body: { requests: [] } }));
|
|
40
40
|
* ```
|
|
41
41
|
*
|
|
42
42
|
* @see https://developer.ebay.com/api-docs/sell/inventory/resources/offer/methods/bulkCreateOffer
|
|
@@ -45,9 +45,9 @@ export const createInventoryOffersMethods = (client) => ({
|
|
|
45
45
|
const path = `${INVENTORY_BASE_PATH}/bulk_create_offer`;
|
|
46
46
|
return Effect.gen(function* () {
|
|
47
47
|
const validatedInput = yield* requireObjectEffect(input, 'input');
|
|
48
|
-
const
|
|
49
|
-
yield* Effect.forEach(
|
|
50
|
-
return yield* requestPostEffect(client, path,
|
|
48
|
+
const bulkOfferRequest = yield* requireObjectEffect(validatedInput.body, 'body');
|
|
49
|
+
yield* Effect.forEach(bulkOfferRequest.requests ?? [], (offerRequest, index) => validateOfferFormatEffect(offerRequest, `body.requests[${index}]`), { discard: true });
|
|
50
|
+
return yield* requestPostEffect(client, path, bulkOfferRequest);
|
|
51
51
|
});
|
|
52
52
|
},
|
|
53
53
|
/**
|
|
@@ -58,7 +58,7 @@ export const createInventoryOffersMethods = (client) => ({
|
|
|
58
58
|
*
|
|
59
59
|
* @example
|
|
60
60
|
* ```ts
|
|
61
|
-
* const
|
|
61
|
+
* const publishedOffers = await Effect.runPromise(inventoryApi.bulkPublishOffer({ body: { offers: [] } }));
|
|
62
62
|
* ```
|
|
63
63
|
*
|
|
64
64
|
* @see https://developer.ebay.com/api-docs/sell/inventory/resources/offer/methods/bulkPublishOffer
|
|
@@ -67,8 +67,8 @@ export const createInventoryOffersMethods = (client) => ({
|
|
|
67
67
|
const path = `${INVENTORY_BASE_PATH}/bulk_publish_offer`;
|
|
68
68
|
return Effect.gen(function* () {
|
|
69
69
|
const validatedInput = yield* requireObjectEffect(input, 'input');
|
|
70
|
-
const
|
|
71
|
-
return yield* requestPostEffect(client, path,
|
|
70
|
+
const bulkPublishRequest = yield* requireObjectEffect(validatedInput.body, 'body');
|
|
71
|
+
return yield* requestPostEffect(client, path, bulkPublishRequest);
|
|
72
72
|
});
|
|
73
73
|
},
|
|
74
74
|
/**
|
|
@@ -116,7 +116,7 @@ export const createInventoryOffersMethods = (client) => ({
|
|
|
116
116
|
const format = yield* optionalStringEffect(validatedInput.format, 'format');
|
|
117
117
|
const marketplaceId = yield* optionalStringEffect(validatedInput.marketplaceId, 'marketplaceId');
|
|
118
118
|
const uniqueSkus = [...new Set(validatedInput.skus)];
|
|
119
|
-
const
|
|
119
|
+
const skuResults = yield* Effect.forEach(uniqueSkus, (sku) => Effect.map(Effect.either(getOffersEffect(client, {
|
|
120
120
|
sku,
|
|
121
121
|
format,
|
|
122
122
|
marketplaceId,
|
|
@@ -127,13 +127,13 @@ export const createInventoryOffersMethods = (client) => ({
|
|
|
127
127
|
status: 'failure',
|
|
128
128
|
error: { type: outcome.left._tag, message: outcome.left.message },
|
|
129
129
|
}), { concurrency: BATCH_GET_OFFERS_CONCURRENCY });
|
|
130
|
-
const successCount =
|
|
130
|
+
const successCount = skuResults.filter((skuResult) => skuResult.status === 'success').length;
|
|
131
131
|
return {
|
|
132
132
|
requestedSkuCount: validatedInput.skus.length,
|
|
133
133
|
uniqueSkuCount: uniqueSkus.length,
|
|
134
134
|
successCount,
|
|
135
|
-
failureCount:
|
|
136
|
-
results,
|
|
135
|
+
failureCount: skuResults.length - successCount,
|
|
136
|
+
results: skuResults,
|
|
137
137
|
};
|
|
138
138
|
}),
|
|
139
139
|
/**
|
|
@@ -153,9 +153,9 @@ export const createInventoryOffersMethods = (client) => ({
|
|
|
153
153
|
const path = `${INVENTORY_BASE_PATH}/offer`;
|
|
154
154
|
return Effect.gen(function* () {
|
|
155
155
|
const validatedInput = yield* requireObjectEffect(input, 'input');
|
|
156
|
-
const
|
|
157
|
-
yield* validateOfferFormatEffect(
|
|
158
|
-
return yield* requestPostEffect(client, path,
|
|
156
|
+
const offerDetails = yield* requireObjectEffect(validatedInput.body, 'body');
|
|
157
|
+
yield* validateOfferFormatEffect(offerDetails, 'body');
|
|
158
|
+
return yield* requestPostEffect(client, path, offerDetails);
|
|
159
159
|
});
|
|
160
160
|
},
|
|
161
161
|
/**
|
|
@@ -199,9 +199,9 @@ export const createInventoryOffersMethods = (client) => ({
|
|
|
199
199
|
return Effect.gen(function* () {
|
|
200
200
|
const validatedInput = yield* requireObjectEffect(input, 'input');
|
|
201
201
|
const offerId = yield* requireStringEffect(validatedInput.offerId, 'offerId');
|
|
202
|
-
const
|
|
203
|
-
yield* validateOfferFormatEffect(
|
|
204
|
-
return yield* requestPutEffect(client, `${basePath}/offer/${offerId}`,
|
|
202
|
+
const offerUpdate = yield* requireObjectEffect(validatedInput.body, 'body');
|
|
203
|
+
yield* validateOfferFormatEffect(offerUpdate, 'body');
|
|
204
|
+
return yield* requestPutEffect(client, `${basePath}/offer/${offerId}`, offerUpdate);
|
|
205
205
|
});
|
|
206
206
|
},
|
|
207
207
|
/**
|
|
@@ -244,8 +244,8 @@ export const createInventoryOffersMethods = (client) => ({
|
|
|
244
244
|
const path = `${INVENTORY_BASE_PATH}/offer/get_listing_fees`;
|
|
245
245
|
return Effect.gen(function* () {
|
|
246
246
|
const validatedInput = yield* requireObjectEffect(input, 'input');
|
|
247
|
-
const
|
|
248
|
-
return yield* requestPostEffect(client, path,
|
|
247
|
+
const listingFeesRequest = yield* requireObjectEffect(validatedInput.body, 'body');
|
|
248
|
+
return yield* requestPostEffect(client, path, listingFeesRequest);
|
|
249
249
|
});
|
|
250
250
|
},
|
|
251
251
|
/**
|
|
@@ -290,8 +290,8 @@ export const createInventoryOffersMethods = (client) => ({
|
|
|
290
290
|
const path = `${INVENTORY_BASE_PATH}/offer/publish_by_inventory_item_group`;
|
|
291
291
|
return Effect.gen(function* () {
|
|
292
292
|
const validatedInput = yield* requireObjectEffect(input, 'input');
|
|
293
|
-
const
|
|
294
|
-
return yield* requestPostEffect(client, path,
|
|
293
|
+
const publishGroupRequest = yield* requireObjectEffect(validatedInput.body, 'body');
|
|
294
|
+
return yield* requestPostEffect(client, path, publishGroupRequest);
|
|
295
295
|
});
|
|
296
296
|
},
|
|
297
297
|
/**
|
|
@@ -336,8 +336,8 @@ export const createInventoryOffersMethods = (client) => ({
|
|
|
336
336
|
const path = `${INVENTORY_BASE_PATH}/offer/withdraw_by_inventory_item_group`;
|
|
337
337
|
return Effect.gen(function* () {
|
|
338
338
|
const validatedInput = yield* requireObjectEffect(input, 'input');
|
|
339
|
-
const
|
|
340
|
-
return yield* requestPostEffect(client, path,
|
|
339
|
+
const withdrawGroupRequest = yield* requireObjectEffect(validatedInput.body, 'body');
|
|
340
|
+
return yield* requestPostEffect(client, path, withdrawGroupRequest);
|
|
341
341
|
});
|
|
342
342
|
},
|
|
343
343
|
});
|
|
@@ -15,7 +15,7 @@ const TASKS_PATH = `${STORE_PATH}/tasks`;
|
|
|
15
15
|
const startCategoryTask = (method, path, send) => Effect.tryPromise({
|
|
16
16
|
try: send,
|
|
17
17
|
catch: (cause) => new EbayApiError({ method, path, cause }),
|
|
18
|
-
}).pipe(Effect.flatMap((
|
|
18
|
+
}).pipe(Effect.flatMap((taskResponse) => locatedResourceId(taskResponse.headers.location, TASKS_PATH).pipe(Effect.mapError((error) => new EbayApiError({ method, path, cause: error.cause })))), Effect.map((task) => ({ taskId: task.id, location: task.location })));
|
|
19
19
|
/** Stores API - eBay Store details and store category management. */
|
|
20
20
|
export class StoresApi {
|
|
21
21
|
client;
|
|
@@ -107,12 +107,12 @@ export class StoresApi {
|
|
|
107
107
|
const path = `${STORE_PATH}/categories`;
|
|
108
108
|
return Effect.gen(function* () {
|
|
109
109
|
const endpointInput = yield* requireObjectEffect(input, 'input');
|
|
110
|
-
const
|
|
110
|
+
const addCategoryRequest = {
|
|
111
111
|
categoryName: yield* requireStringEffect(endpointInput.categoryName, 'categoryName'),
|
|
112
112
|
destinationParentCategoryId: yield* optionalStringEffect(endpointInput.destinationParentCategoryId, 'destinationParentCategoryId'),
|
|
113
113
|
listingDestinationCategoryId: yield* optionalStringEffect(endpointInput.listingDestinationCategoryId, 'listingDestinationCategoryId'),
|
|
114
114
|
};
|
|
115
|
-
return yield* startCategoryTask('POST', path, () => client.postForResponse(path,
|
|
115
|
+
return yield* startCategoryTask('POST', path, () => client.postForResponse(path, addCategoryRequest));
|
|
116
116
|
});
|
|
117
117
|
};
|
|
118
118
|
/**
|
|
@@ -136,11 +136,11 @@ export class StoresApi {
|
|
|
136
136
|
return Effect.gen(function* () {
|
|
137
137
|
const endpointInput = yield* requireObjectEffect(input, 'input');
|
|
138
138
|
const categoryId = yield* requireStringEffect(endpointInput.categoryId, 'categoryId');
|
|
139
|
-
const
|
|
139
|
+
const renameCategoryRequest = {
|
|
140
140
|
categoryName: yield* requireStringEffect(endpointInput.categoryName, 'categoryName'),
|
|
141
141
|
};
|
|
142
142
|
const path = `${STORE_PATH}/categories/${encodeURIComponent(categoryId)}`;
|
|
143
|
-
return yield* startCategoryTask('PUT', path, () => client.putForResponse(path,
|
|
143
|
+
return yield* startCategoryTask('PUT', path, () => client.putForResponse(path, renameCategoryRequest));
|
|
144
144
|
});
|
|
145
145
|
};
|
|
146
146
|
/**
|
|
@@ -166,9 +166,9 @@ export class StoresApi {
|
|
|
166
166
|
const endpointInput = yield* requireObjectEffect(input, 'input');
|
|
167
167
|
const categoryId = yield* requireStringEffect(endpointInput.categoryId, 'categoryId');
|
|
168
168
|
const listingDestinationCategoryId = yield* optionalStringEffect(endpointInput.listingDestinationCategoryId, 'listingDestinationCategoryId');
|
|
169
|
-
const
|
|
169
|
+
const deleteCategoryRequest = listingDestinationCategoryId === undefined ? undefined : { listingDestinationCategoryId };
|
|
170
170
|
const path = `${STORE_PATH}/categories/${encodeURIComponent(categoryId)}`;
|
|
171
|
-
return yield* startCategoryTask('DELETE', path, () => client.deleteForResponse(path, undefined,
|
|
171
|
+
return yield* startCategoryTask('DELETE', path, () => client.deleteForResponse(path, undefined, deleteCategoryRequest));
|
|
172
172
|
});
|
|
173
173
|
};
|
|
174
174
|
/**
|
|
@@ -192,12 +192,12 @@ export class StoresApi {
|
|
|
192
192
|
const path = `${STORE_PATH}/categories/move_category`;
|
|
193
193
|
return Effect.gen(function* () {
|
|
194
194
|
const endpointInput = yield* requireObjectEffect(input, 'input');
|
|
195
|
-
const
|
|
195
|
+
const moveCategoryRequest = {
|
|
196
196
|
categoryId: yield* requireStringEffect(endpointInput.categoryId, 'categoryId'),
|
|
197
197
|
destinationParentCategoryId: yield* requireStringEffect(endpointInput.destinationParentCategoryId, 'destinationParentCategoryId'),
|
|
198
198
|
listingDestinationCategoryId: yield* optionalStringEffect(endpointInput.listingDestinationCategoryId, 'listingDestinationCategoryId'),
|
|
199
199
|
};
|
|
200
|
-
return yield* startCategoryTask('POST', path, () => client.postForResponse(path,
|
|
200
|
+
return yield* startCategoryTask('POST', path, () => client.postForResponse(path, moveCategoryRequest));
|
|
201
201
|
});
|
|
202
202
|
};
|
|
203
203
|
}
|