ebay-mcp 1.17.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.
Files changed (178) hide show
  1. package/README.md +92 -53
  2. package/build/api/account-management/accountV2.js +347 -0
  3. package/build/api/account-management/finances.js +289 -0
  4. package/build/api/analytics-and-report/analytics.js +1 -1
  5. package/build/api/{client.js → client/ebayApiClient.js} +83 -36
  6. package/build/api/{clientTrading.js → client/tradingApiClient.js} +22 -22
  7. package/build/api/communication/feedback.js +21 -21
  8. package/build/api/communication/message.js +23 -23
  9. package/build/api/communication/negotiation.js +7 -7
  10. package/build/api/communication/notification.js +52 -52
  11. package/build/api/developer/developer.js +3 -3
  12. package/build/api/{index.js → ebaySellerApi.js} +28 -4
  13. package/build/api/listing-management/feed.js +91 -0
  14. package/build/api/listing-management/feedReportTasks.js +107 -0
  15. package/build/api/listing-management/feedRequest.js +91 -0
  16. package/build/api/listing-management/feedSchedules.js +95 -0
  17. package/build/api/listing-management/feedTasks.js +91 -0
  18. package/build/api/listing-management/items.js +22 -22
  19. package/build/api/listing-management/locations.js +4 -4
  20. package/build/api/listing-management/media.js +14 -14
  21. package/build/api/listing-management/mediaAttach.js +14 -14
  22. package/build/api/listing-management/mediaResources.js +22 -39
  23. package/build/api/listing-management/offerFormat.js +1 -1
  24. package/build/api/listing-management/offers.js +23 -23
  25. package/build/api/listing-management/stores.js +203 -0
  26. package/build/api/listing-metadata/charity.js +76 -0
  27. package/build/api/listing-metadata/metadata.js +31 -11
  28. package/build/api/listing-metadata/metadataShipping.js +117 -0
  29. package/build/api/listing-metadata/taxonomy.js +52 -7
  30. package/build/api/marketing-and-promotions/ads.js +34 -34
  31. package/build/api/marketing-and-promotions/campaigns.js +21 -21
  32. package/build/api/marketing-and-promotions/promotions.js +24 -24
  33. package/build/api/marketing-and-promotions/reports.js +7 -7
  34. package/build/api/marketing-and-promotions/shared.js +0 -3
  35. package/build/api/order-management/dispute.js +11 -9
  36. package/build/api/order-management/fulfillment.js +4 -4
  37. package/build/api/order-management/logistics.js +150 -0
  38. package/build/api/other/browseMappers.js +15 -13
  39. package/build/api/other/browseValidators.js +4 -4
  40. package/build/api/other/edelivery.js +19 -19
  41. package/build/api/other/finding.js +13 -13
  42. package/build/api/other/translation.js +2 -2
  43. package/build/api/other/vero.js +2 -2
  44. package/build/api/shared/download.js +79 -0
  45. package/build/api/shared/location.js +33 -0
  46. package/build/api/shared/request.js +69 -11
  47. package/build/api/trading/listingFormat.js +37 -30
  48. package/build/api/trading/trading.js +33 -33
  49. package/build/auth/credentialSession.js +5 -5
  50. package/build/auth/oauth.js +3 -3
  51. package/build/auth/oauthHelper.js +24 -24
  52. package/build/auth/oauthMetadata.js +4 -4
  53. package/build/auth/oauthMiddleware.js +16 -16
  54. package/build/auth/scopeUtils.js +24 -3
  55. package/build/auth/tokenVerifier.js +23 -23
  56. package/build/config/environment.js +10 -45
  57. package/build/config/oauthScopes.js +132 -0
  58. package/build/config/toolFamilies.js +4 -0
  59. package/build/index.js +5 -5
  60. package/build/mcp/httpTransport.js +32 -20
  61. package/build/mcp/runtime.js +12 -12
  62. package/build/mcp/toolGating.js +6 -12
  63. package/build/mcp/uiBridge.js +3 -3
  64. package/build/schemas/account-management/account.js +2 -52
  65. package/build/schemas/account-management/accountV2.js +294 -0
  66. package/build/schemas/account-management/finances.js +143 -0
  67. package/build/schemas/analytics/analytics.js +2 -48
  68. package/build/schemas/communication/messages.js +2 -46
  69. package/build/schemas/developer/developer.js +1 -27
  70. package/build/schemas/fulfillment/logistics.js +115 -0
  71. package/build/schemas/fulfillment/orders.js +2 -47
  72. package/build/schemas/inventory-management/feed.js +217 -0
  73. package/build/schemas/inventory-management/inventory.js +2 -50
  74. package/build/schemas/inventory-management/media.js +2 -2
  75. package/build/schemas/inventory-management/mediaDocuments.js +1 -1
  76. package/build/schemas/inventory-management/stores.js +42 -0
  77. package/build/schemas/marketing/ads.js +2 -2
  78. package/build/schemas/marketing/campaigns.js +2 -2
  79. package/build/schemas/marketing/common.js +2 -2
  80. package/build/schemas/marketing/marketing.js +0 -1
  81. package/build/schemas/marketing/promotions.js +2 -2
  82. package/build/schemas/marketing/reports.js +2 -2
  83. package/build/schemas/metadata/metadata.js +2 -90
  84. package/build/schemas/metadata/shipping.js +16 -0
  85. package/build/schemas/other/browse.js +2 -2
  86. package/build/schemas/other/finding.js +2 -2
  87. package/build/schemas/other/otherApis.js +2 -114
  88. package/build/schemas/taxonomy/categoryTree.js +8 -0
  89. package/build/schemas/taxonomy/charity.js +41 -0
  90. package/build/schemas/taxonomy/taxonomy.js +2 -69
  91. package/build/scripts/autoSetup.js +3 -3
  92. package/build/scripts/{buildUi.js → buildMcpApps.js} +13 -13
  93. package/build/scripts/devSync.js +34 -70
  94. package/build/scripts/diagnostics.js +15 -16
  95. package/build/scripts/interactiveSetup.js +25 -25
  96. package/build/scripts/scopeHelper.js +2 -2
  97. package/build/scripts/securityChecker.js +20 -20
  98. package/build/scripts/setup.js +76 -76
  99. package/build/scripts/setupShared.js +5 -30
  100. package/build/scripts/setupValidator.js +9 -9
  101. package/build/scripts/setupWizard.js +23 -23
  102. package/build/scripts/skills.js +14 -17
  103. package/build/scripts/specRefs.js +55 -0
  104. package/build/scripts/specSources.js +144 -0
  105. package/build/serverHttp.js +4 -7
  106. package/build/skills/content.js +13 -13
  107. package/build/skills/install.js +9 -9
  108. package/build/skills/registrySnapshot.js +7 -3
  109. package/build/skills/render.js +2 -2
  110. package/build/tools/categories/accountV2.js +106 -0
  111. package/build/tools/categories/charity.js +21 -0
  112. package/build/tools/categories/communication.js +1 -1
  113. package/build/tools/categories/connector.js +19 -16
  114. package/build/tools/categories/feed.js +183 -0
  115. package/build/tools/categories/finances.js +86 -0
  116. package/build/tools/categories/fulfillment.js +4 -4
  117. package/build/tools/categories/index.js +12 -2
  118. package/build/tools/categories/inventory.js +1 -1
  119. package/build/tools/categories/logistics.js +52 -0
  120. package/build/tools/categories/metadata.js +38 -1
  121. package/build/tools/categories/stores.js +64 -0
  122. package/build/tools/categories/taxonomy.js +18 -1
  123. package/build/tools/categories/tokenManagement.js +8 -8
  124. package/build/tools/contracts.js +2 -2
  125. package/build/tools/defineTool.js +27 -12
  126. package/build/tools/fileResult.js +30 -0
  127. package/build/tools/registry.js +2 -2
  128. package/build/tools/schemas.js +2 -2
  129. package/build/tools/ui/mapHelpers.js +12 -12
  130. package/build/tools/ui/maps.js +101 -97
  131. package/build/tools/ui/viewModels.js +2 -2
  132. package/build/utils/apiStatusFeed.js +12 -12
  133. package/build/utils/communication/feedback.js +3 -3
  134. package/build/utils/communication/message.js +3 -3
  135. package/build/utils/communication/negotiation.js +3 -3
  136. package/build/utils/communication/notification.js +3 -3
  137. package/build/utils/entryModule.js +33 -0
  138. package/build/utils/envFile.js +47 -0
  139. package/build/utils/envParser.js +5 -5
  140. package/build/utils/errors.js +4 -4
  141. package/build/utils/http.js +60 -41
  142. package/build/utils/localFeedFiles.js +61 -0
  143. package/build/utils/localMedia.js +18 -6
  144. package/build/utils/logRedaction.js +21 -0
  145. package/build/utils/logger.js +52 -33
  146. package/build/utils/other/compliance.js +3 -3
  147. package/build/utils/other/identity.js +3 -3
  148. package/build/utils/other/translation.js +3 -3
  149. package/build/utils/other/vero.js +3 -3
  150. package/build/utils/schemaHelpers.js +2 -2
  151. package/build/utils/tokenUtils.js +2 -2
  152. package/build/utils/trading/trading.js +1 -1
  153. package/build/utils/version.js +1 -1
  154. package/build/utils/zodIssues.js +14 -0
  155. package/package.json +9 -12
  156. package/README.de.md +0 -422
  157. package/README.es.md +0 -422
  158. package/README.fr.md +0 -422
  159. package/README.ja.md +0 -422
  160. package/README.ko.md +0 -422
  161. package/README.pt-BR.md +0 -422
  162. package/README.ru.md +0 -422
  163. package/README.zh-CN.md +0 -422
  164. package/build/schemas/index.js +0 -76
  165. package/build/schemas/marketing/jsonSchemas.js +0 -118
  166. package/build/scripts/downloadSpecs.js +0 -117
  167. package/build/scripts/updateApiStatusDoc.js +0 -71
  168. package/build/utils/effectSchema.js +0 -203
  169. package/build/utils/effectSchemaAdapter.js +0 -121
  170. package/build/utils/effectSchemaChainMethods.js +0 -146
  171. package/build/utils/effectSchemaRefinements.js +0 -104
  172. package/build/utils/effectSchemaStringMethods.js +0 -63
  173. package/build/utils/effectSchemaTypes.js +0 -47
  174. package/docs/auth/production_scopes.json +0 -111
  175. package/docs/auth/sandbox_scopes.json +0 -142
  176. /package/build/api/{clientRequestError.js → client/ebayClientRequestError.js} +0 -0
  177. /package/build/api/{rateLimitTracker.js → client/rateLimitTracker.js} +0 -0
  178. /package/build/api/{clientTradingError.js → client/tradingApiFailure.js} +0 -0
@@ -1,34 +1,15 @@
1
- import { EbayApiError, EndpointInputError } from '../../api/shared/request.js';
1
+ import { locatedResourceId } from '../../api/shared/location.js';
2
+ import { decodeEndpointInputEffect, EbayApiError } from '../../api/shared/request.js';
2
3
  import { getIdentityBaseUrl, getMediaBaseUrl } from '../../config/environment.js';
3
4
  import { createDocumentFromUrlInputSchema, createDocumentInputSchema, createImageFromUrlInputSchema, documentIdInputSchema, postOrderDocumentMetadataSchema, } from '../../schemas/inventory-management/mediaDocuments.js';
4
- import { decodeEffectSchema } from '../../utils/effectSchema.js';
5
5
  import { Effect } from 'effect';
6
6
  const BASE_PATH = '/commerce/media/v1_beta';
7
7
  const UPLOAD_TIMEOUT_MS = 10 * 60_000;
8
- const inputFailure = (cause) => new EndpointInputError({ parameter: 'input', message: cause.message });
9
8
  const uploadForm = (file) => {
10
9
  const form = new FormData();
11
10
  form.append('file', new Blob([new Uint8Array(file.bytes)], { type: file.mimeType }), file.fileName);
12
11
  return form;
13
12
  };
14
- const locationId = (location, path) => Effect.try({
15
- try: () => {
16
- if (!location) {
17
- throw new Error('eBay returned no Location header');
18
- }
19
- const url = new URL(location);
20
- const prefix = `${path}/`;
21
- const segment = url.pathname.slice(prefix.length);
22
- if (url.protocol !== 'https:' ||
23
- !url.pathname.startsWith(prefix) ||
24
- !segment ||
25
- segment.includes('/')) {
26
- throw new Error('eBay returned an invalid resource Location');
27
- }
28
- return { location, id: decodeURIComponent(segment) };
29
- },
30
- catch: (cause) => new EbayApiError({ method: 'POST', path, cause }),
31
- });
32
13
  /**
33
14
  * Creates endpoint methods for image URLs and documents on the Media API.
34
15
  * @param client - Shared authenticated HTTP client.
@@ -51,16 +32,16 @@ export const createMediaResourceMethods = (client) => {
51
32
  * @see https://developer.ebay.com/api-docs/commerce/media/resources/image/methods/createImageFromUrl
52
33
  */
53
34
  const createImageFromUrl = (input) => Effect.gen(function* () {
54
- const body = yield* decodeEffectSchema(createImageFromUrlInputSchema, input).pipe(Effect.mapError(inputFailure));
35
+ const imageSource = yield* decodeEndpointInputEffect(createImageFromUrlInputSchema, input);
55
36
  const path = '/image/create_image_from_url';
56
- const response = yield* Effect.tryPromise({
57
- try: () => client.postForResponse(url(path), body, {
37
+ const imageResponse = yield* Effect.tryPromise({
38
+ try: () => client.postForResponse(url(path), imageSource, {
58
39
  absolute: true,
59
40
  }),
60
41
  catch: failure('POST', path),
61
42
  });
62
- const resource = yield* locationId(response.headers.location, `${BASE_PATH}/image`);
63
- return { imageId: resource.id, location: resource.location, image: response.data };
43
+ const resource = yield* locatedResourceId(imageResponse.headers.location, `${BASE_PATH}/image`);
44
+ return { imageId: resource.id, location: resource.location, image: imageResponse.data };
64
45
  });
65
46
  /**
66
47
  * Stages a listing document for subsequent upload.
@@ -70,9 +51,11 @@ export const createMediaResourceMethods = (client) => {
70
51
  * @see https://developer.ebay.com/api-docs/commerce/media/resources/document/methods/createDocument
71
52
  */
72
53
  const createDocument = (input) => Effect.gen(function* () {
73
- const body = yield* decodeEffectSchema(createDocumentInputSchema, input).pipe(Effect.mapError(inputFailure));
54
+ const documentRequest = yield* decodeEndpointInputEffect(createDocumentInputSchema, input);
74
55
  return yield* Effect.tryPromise({
75
- try: () => client.post(url('/document'), body, { absolute: true }),
56
+ try: () => client.post(url('/document'), documentRequest, {
57
+ absolute: true,
58
+ }),
76
59
  catch: failure('POST', '/document'),
77
60
  });
78
61
  });
@@ -84,10 +67,10 @@ export const createMediaResourceMethods = (client) => {
84
67
  * @see https://developer.ebay.com/api-docs/commerce/media/resources/document/methods/createDocumentFromUrl
85
68
  */
86
69
  const createDocumentFromUrl = (input) => Effect.gen(function* () {
87
- const body = yield* decodeEffectSchema(createDocumentFromUrlInputSchema, input).pipe(Effect.mapError(inputFailure));
70
+ const documentRequest = yield* decodeEndpointInputEffect(createDocumentFromUrlInputSchema, input);
88
71
  const path = '/document/create_document_from_url';
89
72
  return yield* Effect.tryPromise({
90
- try: () => client.post(url(path), body, { absolute: true }),
73
+ try: () => client.post(url(path), documentRequest, { absolute: true }),
91
74
  catch: failure('POST', path),
92
75
  });
93
76
  });
@@ -99,7 +82,7 @@ export const createMediaResourceMethods = (client) => {
99
82
  * @see https://developer.ebay.com/api-docs/commerce/media/resources/document/methods/getDocument
100
83
  */
101
84
  const getDocument = (input) => Effect.gen(function* () {
102
- const { documentId } = yield* decodeEffectSchema(documentIdInputSchema, input).pipe(Effect.mapError(inputFailure));
85
+ const { documentId } = yield* decodeEndpointInputEffect(documentIdInputSchema, input);
103
86
  const path = `/document/${encodeURIComponent(documentId)}`;
104
87
  return yield* Effect.tryPromise({
105
88
  try: () => client.get(url(path), undefined, { absolute: true }),
@@ -114,7 +97,7 @@ export const createMediaResourceMethods = (client) => {
114
97
  * @see https://developer.ebay.com/api-docs/commerce/media/resources/document/methods/uploadDocument
115
98
  */
116
99
  const uploadDocument = (input) => Effect.gen(function* () {
117
- const { documentId } = yield* decodeEffectSchema(documentIdInputSchema, input).pipe(Effect.mapError(inputFailure));
100
+ const { documentId } = yield* decodeEndpointInputEffect(documentIdInputSchema, input);
118
101
  const path = `/document/${encodeURIComponent(documentId)}/upload`;
119
102
  return yield* Effect.tryPromise({
120
103
  try: () => client.post(url(path), uploadForm(input.file), {
@@ -132,20 +115,20 @@ export const createMediaResourceMethods = (client) => {
132
115
  * @see https://developer.ebay.com/api-docs/commerce/media/resources/post_order/methods/uploadPostOrderDocument
133
116
  */
134
117
  const uploadPostOrderDocument = (input) => Effect.gen(function* () {
135
- const metadata = yield* decodeEffectSchema(postOrderDocumentMetadataSchema, input).pipe(Effect.mapError(inputFailure));
118
+ const metadata = yield* decodeEndpointInputEffect(postOrderDocumentMetadataSchema, input);
136
119
  const form = uploadForm(input.file);
137
- for (const [key, value] of Object.entries(metadata)) {
138
- form.append(key, value);
120
+ for (const [fieldName, fieldValue] of Object.entries(metadata)) {
121
+ form.append(fieldName, fieldValue);
139
122
  }
140
123
  const path = '/post_order/document';
141
- const response = yield* Effect.tryPromise({
124
+ const uploadResponse = yield* Effect.tryPromise({
142
125
  try: () => client.postForResponse(url(path, true), form, {
143
126
  absolute: true,
144
127
  timeoutMs: UPLOAD_TIMEOUT_MS,
145
128
  }),
146
129
  catch: failure('POST', path),
147
130
  });
148
- const resource = yield* locationId(response.headers.location, `${BASE_PATH}${path}`);
131
+ const resource = yield* locatedResourceId(uploadResponse.headers.location, `${BASE_PATH}${path}`);
149
132
  return { documentId: resource.id, location: resource.location };
150
133
  });
151
134
  /**
@@ -156,7 +139,7 @@ export const createMediaResourceMethods = (client) => {
156
139
  * @see https://developer.ebay.com/api-docs/commerce/media/resources/post_order/methods/downloadPostOrderDocument
157
140
  */
158
141
  const downloadPostOrderDocument = (input) => Effect.gen(function* () {
159
- const { documentId } = yield* decodeEffectSchema(documentIdInputSchema, input).pipe(Effect.mapError(inputFailure));
142
+ const { documentId } = yield* decodeEndpointInputEffect(documentIdInputSchema, input);
160
143
  const path = `/post_order/document/${encodeURIComponent(documentId)}`;
161
144
  return yield* Effect.tryPromise({
162
145
  try: () => client.get(url(path, true), undefined, {
@@ -175,7 +158,7 @@ export const createMediaResourceMethods = (client) => {
175
158
  * @see https://developer.ebay.com/api-docs/commerce/media/resources/post_order/methods/removePostOrderDocument
176
159
  */
177
160
  const removePostOrderDocument = (input) => Effect.gen(function* () {
178
- const { documentId } = yield* decodeEffectSchema(documentIdInputSchema, input).pipe(Effect.mapError(inputFailure));
161
+ const { documentId } = yield* decodeEndpointInputEffect(documentIdInputSchema, input);
179
162
  const path = `/post_order/document/${encodeURIComponent(documentId)}`;
180
163
  yield* Effect.tryPromise({
181
164
  try: () => client.delete(url(path, true), { absolute: true }),
@@ -102,7 +102,7 @@ export const findOfferFormatViolation = (offer, parameter) => {
102
102
  *
103
103
  * @example
104
104
  * ```ts
105
- * yield* validateOfferFormatEffect(body, 'body');
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 result = await Effect.runPromise(inventoryApi.bulkCreateOffer({ body: { requests: [] } }));
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 body = yield* requireObjectEffect(validatedInput.body, 'body');
49
- yield* Effect.forEach(body.requests ?? [], (request, index) => validateOfferFormatEffect(request, `body.requests[${index}]`), { discard: true });
50
- return yield* requestPostEffect(client, path, body);
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 result = await Effect.runPromise(inventoryApi.bulkPublishOffer({ body: { offers: [] } }));
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 body = yield* requireObjectEffect(validatedInput.body, 'body');
71
- return yield* requestPostEffect(client, path, body);
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 results = yield* Effect.forEach(uniqueSkus, (sku) => Effect.map(Effect.either(getOffersEffect(client, {
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 = results.filter((result) => result.status === 'success').length;
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: results.length - successCount,
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 body = yield* requireObjectEffect(validatedInput.body, 'body');
157
- yield* validateOfferFormatEffect(body, 'body');
158
- return yield* requestPostEffect(client, path, body);
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 body = yield* requireObjectEffect(validatedInput.body, 'body');
203
- yield* validateOfferFormatEffect(body, 'body');
204
- return yield* requestPutEffect(client, `${basePath}/offer/${offerId}`, body);
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 body = yield* requireObjectEffect(validatedInput.body, 'body');
248
- return yield* requestPostEffect(client, path, body);
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 body = yield* requireObjectEffect(validatedInput.body, 'body');
294
- return yield* requestPostEffect(client, path, body);
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 body = yield* requireObjectEffect(validatedInput.body, 'body');
340
- return yield* requestPostEffect(client, path, body);
339
+ const withdrawGroupRequest = yield* requireObjectEffect(validatedInput.body, 'body');
340
+ return yield* requestPostEffect(client, path, withdrawGroupRequest);
341
341
  });
342
342
  },
343
343
  });
@@ -0,0 +1,203 @@
1
+ import { locatedResourceId } from '../../api/shared/location.js';
2
+ import { EbayApiError, optionalStringEffect, requestGetEffect, requireObjectEffect, requireStringEffect, } from '../../api/shared/request.js';
3
+ import { Effect } from 'effect';
4
+ const STORE_PATH = '/sell/stores/v1/store';
5
+ const TASKS_PATH = `${STORE_PATH}/tasks`;
6
+ /**
7
+ * Sends one asynchronous category change and reads its store task from `Location`.
8
+ * A missing or foreign header fails with an EbayApiError naming this request.
9
+ *
10
+ * @param method - HTTP method of the category change.
11
+ * @param path - eBay REST path of the category change, used in failures.
12
+ * @param send - Client call that keeps the response headers.
13
+ * @returns An Effect with the store task ID and Location, or a typed EbayApiError.
14
+ */
15
+ const startCategoryTask = (method, path, send) => Effect.tryPromise({
16
+ try: send,
17
+ catch: (cause) => new EbayApiError({ method, path, cause }),
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
+ /** Stores API - eBay Store details and store category management. */
20
+ export class StoresApi {
21
+ client;
22
+ constructor(client) {
23
+ this.client = client;
24
+ }
25
+ /**
26
+ * Retrieves the seller's eBay Store details: name, URL, description, and logo.
27
+ *
28
+ * @param _input - Empty object accepted for tool/API shape consistency.
29
+ * @returns An Effect that succeeds with eBay's GetStoreResponseType.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * const store = await Effect.runPromise(storesApi.getStore({}));
34
+ * ```
35
+ *
36
+ * @see https://developer.ebay.com/api-docs/sell/stores/resources/store/methods/getStore
37
+ */
38
+ getStore = (_input = {}) => requestGetEffect(this.client, STORE_PATH);
39
+ /**
40
+ * Retrieves the store's custom category hierarchy (up to three levels).
41
+ *
42
+ * @param _input - Empty object accepted for tool/API shape consistency.
43
+ * @returns An Effect that succeeds with eBay's GetStoreCategoriesResponseType.
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * const { storeCategories } = await Effect.runPromise(storesApi.getStoreCategories({}));
48
+ * ```
49
+ *
50
+ * @see https://developer.ebay.com/api-docs/sell/stores/resources/store/methods/getStoreCategories
51
+ */
52
+ getStoreCategories = (_input = {}) => requestGetEffect(this.client, `${STORE_PATH}/categories`);
53
+ /**
54
+ * Retrieves the status of one asynchronous store category task.
55
+ *
56
+ * @param input - Store task ID returned by a category change.
57
+ * @returns An Effect that succeeds with eBay's GetStoreTaskResponseType.
58
+ *
59
+ * @example
60
+ * ```ts
61
+ * const { task } = await Effect.runPromise(storesApi.getStoreTask({ taskId: 'TASK-1' }));
62
+ * ```
63
+ *
64
+ * @see https://developer.ebay.com/api-docs/sell/stores/resources/store/methods/getStoreTask
65
+ */
66
+ getStoreTask = (input) => {
67
+ const { client } = this;
68
+ return Effect.gen(function* () {
69
+ const endpointInput = yield* requireObjectEffect(input, 'input');
70
+ const taskId = yield* requireStringEffect(endpointInput.taskId, 'taskId');
71
+ return yield* requestGetEffect(client, `${TASKS_PATH}/${encodeURIComponent(taskId)}`);
72
+ });
73
+ };
74
+ /**
75
+ * Retrieves the status of all asynchronous store tasks; each finishes as FAILED or COMPLETED
76
+ * within 24 hours.
77
+ *
78
+ * @param _input - Empty object accepted for tool/API shape consistency.
79
+ * @returns An Effect that succeeds with eBay's GetStoreTasksResponseType.
80
+ *
81
+ * @example
82
+ * ```ts
83
+ * const { task } = await Effect.runPromise(storesApi.getStoreTasks({}));
84
+ * ```
85
+ *
86
+ * @see https://developer.ebay.com/api-docs/sell/stores/resources/store/methods/getStoreTasks
87
+ */
88
+ getStoreTasks = (_input = {}) => requestGetEffect(this.client, TASKS_PATH);
89
+ /**
90
+ * Starts adding one custom store category. eBay answers 202 with the store task URI in
91
+ * `Location`; only one category change can be in flight at a time.
92
+ *
93
+ * @param input - Category name plus optional parent and listing-destination store category IDs.
94
+ * @returns An Effect that succeeds with the store task ID and Location to poll.
95
+ *
96
+ * @example
97
+ * ```ts
98
+ * const { taskId } = await Effect.runPromise(
99
+ * storesApi.addStoreCategory({ categoryName: 'Vintage Cameras' }),
100
+ * );
101
+ * ```
102
+ *
103
+ * @see https://developer.ebay.com/api-docs/sell/stores/resources/store/methods/addStoreCategory
104
+ */
105
+ addStoreCategory = (input) => {
106
+ const { client } = this;
107
+ const path = `${STORE_PATH}/categories`;
108
+ return Effect.gen(function* () {
109
+ const endpointInput = yield* requireObjectEffect(input, 'input');
110
+ const addCategoryRequest = {
111
+ categoryName: yield* requireStringEffect(endpointInput.categoryName, 'categoryName'),
112
+ destinationParentCategoryId: yield* optionalStringEffect(endpointInput.destinationParentCategoryId, 'destinationParentCategoryId'),
113
+ listingDestinationCategoryId: yield* optionalStringEffect(endpointInput.listingDestinationCategoryId, 'listingDestinationCategoryId'),
114
+ };
115
+ return yield* startCategoryTask('POST', path, () => client.postForResponse(path, addCategoryRequest));
116
+ });
117
+ };
118
+ /**
119
+ * Starts renaming one custom store category. eBay answers with the store task URI in
120
+ * `Location`; only one category change can be in flight at a time.
121
+ *
122
+ * @param input - Store category ID (path) and its new name.
123
+ * @returns An Effect that succeeds with the store task ID and Location to poll.
124
+ *
125
+ * @example
126
+ * ```ts
127
+ * const { taskId } = await Effect.runPromise(
128
+ * storesApi.renameStoreCategory({ categoryId: '1234', categoryName: 'Film Cameras' }),
129
+ * );
130
+ * ```
131
+ *
132
+ * @see https://developer.ebay.com/api-docs/sell/stores/resources/store/methods/renameStoreCategory
133
+ */
134
+ renameStoreCategory = (input) => {
135
+ const { client } = this;
136
+ return Effect.gen(function* () {
137
+ const endpointInput = yield* requireObjectEffect(input, 'input');
138
+ const categoryId = yield* requireStringEffect(endpointInput.categoryId, 'categoryId');
139
+ const renameCategoryRequest = {
140
+ categoryName: yield* requireStringEffect(endpointInput.categoryName, 'categoryName'),
141
+ };
142
+ const path = `${STORE_PATH}/categories/${encodeURIComponent(categoryId)}`;
143
+ return yield* startCategoryTask('PUT', path, () => client.putForResponse(path, renameCategoryRequest));
144
+ });
145
+ };
146
+ /**
147
+ * Starts deleting one custom store category. eBay answers 202 with the store task URI in
148
+ * `Location`; only one category change can be in flight at a time. The body is sent only
149
+ * with a listing destination; without one eBay applies its default (the Other category, ID 1).
150
+ *
151
+ * @param input - Store category ID to delete and an optional listing-destination store category.
152
+ * @returns An Effect that succeeds with the store task ID and Location to poll.
153
+ *
154
+ * @example
155
+ * ```ts
156
+ * const { taskId } = await Effect.runPromise(
157
+ * storesApi.deleteStoreCategory({ categoryId: '1234' }),
158
+ * );
159
+ * ```
160
+ *
161
+ * @see https://developer.ebay.com/api-docs/sell/stores/resources/store/methods/deleteStoreCategory
162
+ */
163
+ deleteStoreCategory = (input) => {
164
+ const { client } = this;
165
+ return Effect.gen(function* () {
166
+ const endpointInput = yield* requireObjectEffect(input, 'input');
167
+ const categoryId = yield* requireStringEffect(endpointInput.categoryId, 'categoryId');
168
+ const listingDestinationCategoryId = yield* optionalStringEffect(endpointInput.listingDestinationCategoryId, 'listingDestinationCategoryId');
169
+ const deleteCategoryRequest = listingDestinationCategoryId === undefined ? undefined : { listingDestinationCategoryId };
170
+ const path = `${STORE_PATH}/categories/${encodeURIComponent(categoryId)}`;
171
+ return yield* startCategoryTask('DELETE', path, () => client.deleteForResponse(path, undefined, deleteCategoryRequest));
172
+ });
173
+ };
174
+ /**
175
+ * Starts moving one custom store category under a new parent. eBay answers 202 with the
176
+ * store task URI in `Location`; only one category change can be in flight at a time.
177
+ *
178
+ * @param input - Store category to move, its new parent, and an optional listing destination.
179
+ * @returns An Effect that succeeds with the store task ID and Location to poll.
180
+ *
181
+ * @example
182
+ * ```ts
183
+ * const { taskId } = await Effect.runPromise(
184
+ * storesApi.moveStoreCategory({ categoryId: '1234', destinationParentCategoryId: '-999' }),
185
+ * );
186
+ * ```
187
+ *
188
+ * @see https://developer.ebay.com/api-docs/sell/stores/resources/store/methods/moveStoreCategory
189
+ */
190
+ moveStoreCategory = (input) => {
191
+ const { client } = this;
192
+ const path = `${STORE_PATH}/categories/move_category`;
193
+ return Effect.gen(function* () {
194
+ const endpointInput = yield* requireObjectEffect(input, 'input');
195
+ const moveCategoryRequest = {
196
+ categoryId: yield* requireStringEffect(endpointInput.categoryId, 'categoryId'),
197
+ destinationParentCategoryId: yield* requireStringEffect(endpointInput.destinationParentCategoryId, 'destinationParentCategoryId'),
198
+ listingDestinationCategoryId: yield* optionalStringEffect(endpointInput.listingDestinationCategoryId, 'listingDestinationCategoryId'),
199
+ };
200
+ return yield* startCategoryTask('POST', path, () => client.postForResponse(path, moveCategoryRequest));
201
+ });
202
+ };
203
+ }
@@ -0,0 +1,76 @@
1
+ import { buildEndpointParams, decodeEndpointInputEffect, EndpointInputError, requestGetEffect, } from '../../api/shared/request.js';
2
+ import { getCharityOrgInputSchema, getCharityOrgsInputSchema } from '../../schemas/taxonomy/charity.js';
3
+ import { Effect } from 'effect';
4
+ const BASE_PATH = '/commerce/charity/v1';
5
+ /**
6
+ * eBay documents the Charity API as client-credentials only (api_scope) with a required
7
+ * marketplace header, so every call sends the application token and the caller's marketplace.
8
+ */
9
+ const charityRequestConfig = (marketplaceId) => ({
10
+ headers: { 'X-EBAY-C-MARKETPLACE-ID': marketplaceId },
11
+ tokenType: 'application',
12
+ });
13
+ /** Charity API - charitable organizations supported by eBay for Charity. */
14
+ export class CharityApi {
15
+ client;
16
+ constructor(client) {
17
+ this.client = client;
18
+ }
19
+ /**
20
+ * Retrieves one charitable organization supported by eBay for Charity.
21
+ *
22
+ * @param input - Charity organization ID and the EBAY_US or EBAY_GB marketplace.
23
+ * @returns An Effect that succeeds with eBay's CharityOrg.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * const charity = await Effect.runPromise(
28
+ * charityApi.getCharityOrg({ charityOrgId: '1234', marketplaceId: 'EBAY_US' }),
29
+ * );
30
+ * ```
31
+ *
32
+ * @see https://developer.ebay.com/api-docs/commerce/charity/resources/charity_org/methods/getCharityOrg
33
+ */
34
+ getCharityOrg = (input) => {
35
+ const client = this.client;
36
+ return Effect.gen(function* () {
37
+ const { charityOrgId, marketplaceId } = yield* decodeEndpointInputEffect(getCharityOrgInputSchema, input);
38
+ return yield* requestGetEffect(client, `${BASE_PATH}/charity_org/${encodeURIComponent(charityOrgId)}`, undefined, charityRequestConfig(marketplaceId));
39
+ });
40
+ };
41
+ /**
42
+ * Searches charitable organizations supported by eBay for Charity by keywords or by
43
+ * registration IDs (eBay requires exactly one of the two).
44
+ *
45
+ * @param input - Marketplace, q or registrationIds, and optional limit/offset paging.
46
+ * @returns An Effect that succeeds with eBay's paginated CharitySearchResponse.
47
+ *
48
+ * @example
49
+ * ```ts
50
+ * const results = await Effect.runPromise(
51
+ * charityApi.getCharityOrgs({ marketplaceId: 'EBAY_US', q: 'animal rescue', limit: 10 }),
52
+ * );
53
+ * ```
54
+ *
55
+ * @see https://developer.ebay.com/api-docs/commerce/charity/resources/charity_org/methods/getCharityOrgs
56
+ */
57
+ getCharityOrgs = (input) => {
58
+ const client = this.client;
59
+ return Effect.gen(function* () {
60
+ const search = yield* decodeEndpointInputEffect(getCharityOrgsInputSchema, input);
61
+ if ((search.q === undefined) === (search.registrationIds === undefined)) {
62
+ return yield* Effect.fail(new EndpointInputError({
63
+ parameter: 'q',
64
+ message: 'Supply either q or registrationIds to search charities, but not both',
65
+ }));
66
+ }
67
+ const params = buildEndpointParams({
68
+ q: { wireName: 'q', value: search.q },
69
+ registrationIds: { wireName: 'registration_ids', value: search.registrationIds },
70
+ limit: { wireName: 'limit', value: search.limit },
71
+ offset: { wireName: 'offset', value: search.offset },
72
+ });
73
+ return yield* requestGetEffect(client, `${BASE_PATH}/charity_org`, params, charityRequestConfig(search.marketplaceId));
74
+ });
75
+ };
76
+ }
@@ -1,11 +1,31 @@
1
1
  import { buildEndpointParams, requestGetEffect, requestPostEffect, requireObjectEffect, requireStringEffect, optionalStringEffect, } from '../../api/shared/request.js';
2
2
  import { Effect } from 'effect';
3
- /** Metadata API - marketplace policies, compatibility metadata, and tax jurisdictions. */
3
+ import { createMetadataShippingMethods } from './metadataShipping.js';
4
+ /**
5
+ * Metadata API - marketplace policies, shipping metadata, compatibility metadata, and tax
6
+ * jurisdictions.
7
+ */
4
8
  export class MetadataApi {
5
9
  client;
6
10
  basePath = '/sell/metadata/v1';
11
+ /** Metadata API getExcludeShippingLocations endpoint; see createMetadataShippingMethods. */
12
+ getExcludeShippingLocations;
13
+ /** Metadata API getHandlingTimes endpoint; see createMetadataShippingMethods. */
14
+ getHandlingTimes;
15
+ /** Metadata API getShippingCarriers endpoint; see createMetadataShippingMethods. */
16
+ getShippingCarriers;
17
+ /** Metadata API getShippingLocations endpoint; see createMetadataShippingMethods. */
18
+ getShippingLocations;
19
+ /** Metadata API getShippingServices endpoint; see createMetadataShippingMethods. */
20
+ getShippingServices;
7
21
  constructor(client) {
8
22
  this.client = client;
23
+ const shipping = createMetadataShippingMethods(client);
24
+ this.getExcludeShippingLocations = shipping.getExcludeShippingLocations;
25
+ this.getHandlingTimes = shipping.getHandlingTimes;
26
+ this.getShippingCarriers = shipping.getShippingCarriers;
27
+ this.getShippingLocations = shipping.getShippingLocations;
28
+ this.getShippingServices = shipping.getShippingServices;
9
29
  }
10
30
  /**
11
31
  * Retrieves automotive parts compatibility policies for a marketplace.
@@ -285,8 +305,8 @@ export class MetadataApi {
285
305
  return Effect.gen(function* () {
286
306
  const validatedInput = yield* requireObjectEffect(input, 'input');
287
307
  const marketplaceId = yield* requireStringEffect(validatedInput.marketplaceId, 'marketplaceId');
288
- const body = yield* requireObjectEffect(validatedInput.specification, 'specification');
289
- return yield* requestPostEffect(client, path, body, compatibilityHeaders(marketplaceId));
308
+ const specificationRequest = yield* requireObjectEffect(validatedInput.specification, 'specification');
309
+ return yield* requestPostEffect(client, path, specificationRequest, compatibilityHeaders(marketplaceId));
290
310
  });
291
311
  };
292
312
  /**
@@ -313,8 +333,8 @@ export class MetadataApi {
313
333
  return Effect.gen(function* () {
314
334
  const validatedInput = yield* requireObjectEffect(input, 'input');
315
335
  const marketplaceId = yield* requireStringEffect(validatedInput.marketplaceId, 'marketplaceId');
316
- const body = yield* requireObjectEffect(validatedInput.data, 'data');
317
- return yield* requestPostEffect(client, path, body, compatibilityHeaders(marketplaceId));
336
+ const propertyNamesRequest = yield* requireObjectEffect(validatedInput.data, 'data');
337
+ return yield* requestPostEffect(client, path, propertyNamesRequest, compatibilityHeaders(marketplaceId));
318
338
  });
319
339
  };
320
340
  /**
@@ -341,8 +361,8 @@ export class MetadataApi {
341
361
  return Effect.gen(function* () {
342
362
  const validatedInput = yield* requireObjectEffect(input, 'input');
343
363
  const marketplaceId = yield* requireStringEffect(validatedInput.marketplaceId, 'marketplaceId');
344
- const body = yield* requireObjectEffect(validatedInput.data, 'data');
345
- return yield* requestPostEffect(client, path, body, compatibilityHeaders(marketplaceId));
364
+ const propertyValuesRequest = yield* requireObjectEffect(validatedInput.data, 'data');
365
+ return yield* requestPostEffect(client, path, propertyValuesRequest, compatibilityHeaders(marketplaceId));
346
366
  });
347
367
  };
348
368
  /**
@@ -369,8 +389,8 @@ export class MetadataApi {
369
389
  return Effect.gen(function* () {
370
390
  const validatedInput = yield* requireObjectEffect(input, 'input');
371
391
  const marketplaceId = yield* requireStringEffect(validatedInput.marketplaceId, 'marketplaceId');
372
- const body = yield* requireObjectEffect(validatedInput.data, 'data');
373
- return yield* requestPostEffect(client, path, body, compatibilityHeaders(marketplaceId));
392
+ const multiPropertyValuesRequest = yield* requireObjectEffect(validatedInput.data, 'data');
393
+ return yield* requestPostEffect(client, path, multiPropertyValuesRequest, compatibilityHeaders(marketplaceId));
374
394
  });
375
395
  };
376
396
  /**
@@ -397,8 +417,8 @@ export class MetadataApi {
397
417
  return Effect.gen(function* () {
398
418
  const validatedInput = yield* requireObjectEffect(input, 'input');
399
419
  const marketplaceId = yield* requireStringEffect(validatedInput.marketplaceId, 'marketplaceId');
400
- const body = yield* requireObjectEffect(validatedInput.data, 'data');
401
- return yield* requestPostEffect(client, path, body, compatibilityHeaders(marketplaceId));
420
+ const productRequest = yield* requireObjectEffect(validatedInput.data, 'data');
421
+ return yield* requestPostEffect(client, path, productRequest, compatibilityHeaders(marketplaceId));
402
422
  });
403
423
  };
404
424
  /**