ebay-mcp 1.13.2 → 1.14.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.
Files changed (169) hide show
  1. package/README.de.md +3 -3
  2. package/README.es.md +3 -3
  3. package/README.fr.md +3 -3
  4. package/README.ja.md +3 -3
  5. package/README.ko.md +3 -3
  6. package/README.md +163 -41
  7. package/README.pt-BR.md +3 -3
  8. package/README.ru.md +3 -3
  9. package/README.zh-CN.md +3 -3
  10. package/build/api/account-management/account.js +633 -297
  11. package/build/api/analytics-and-report/analytics.js +111 -65
  12. package/build/api/client.js +199 -140
  13. package/build/api/clientRequestError.js +23 -0
  14. package/build/api/clientTrading.js +213 -0
  15. package/build/api/clientTradingError.js +4 -0
  16. package/build/api/communication/feedback.js +147 -59
  17. package/build/api/communication/message.js +134 -81
  18. package/build/api/communication/negotiation.js +65 -53
  19. package/build/api/communication/notification.js +458 -164
  20. package/build/api/developer/developer.js +99 -45
  21. package/build/api/index.js +23 -8
  22. package/build/api/listing-management/inventory.js +884 -338
  23. package/build/api/listing-metadata/metadata.js +416 -170
  24. package/build/api/listing-metadata/taxonomy.js +187 -42
  25. package/build/api/marketing-and-promotions/marketing.js +1392 -598
  26. package/build/api/marketing-and-promotions/recommendation.js +49 -24
  27. package/build/api/order-management/dispute.js +226 -45
  28. package/build/api/order-management/fulfillment.js +144 -71
  29. package/build/api/order-management/orderIssueHelpers.js +61 -0
  30. package/build/api/other/compliance.js +50 -38
  31. package/build/api/other/edelivery.js +603 -159
  32. package/build/api/other/finding.js +280 -0
  33. package/build/api/other/identity.js +30 -15
  34. package/build/api/other/translation.js +29 -14
  35. package/build/api/other/vero.js +113 -27
  36. package/build/api/rateLimitTracker.js +55 -0
  37. package/build/api/shared/request.js +189 -98
  38. package/build/api/trading/trading.js +154 -87
  39. package/build/auth/credentialSession.js +250 -0
  40. package/build/auth/oauth.js +298 -171
  41. package/build/auth/{oauth-metadata.js → oauthMetadata.js} +22 -6
  42. package/build/auth/oauthMiddleware.js +104 -0
  43. package/build/auth/{scope-utils.js → scopeUtils.js} +101 -28
  44. package/build/auth/tokenVerifier.js +243 -0
  45. package/build/auth/tokenVerifierError.js +21 -0
  46. package/build/config/environment.js +148 -113
  47. package/build/config/{tool-families.js → toolFamilies.js} +30 -14
  48. package/build/index.js +25 -19
  49. package/build/mcp/{http-transport.js → httpTransport.js} +102 -52
  50. package/build/mcp/readOnlyFilter.js +67 -0
  51. package/build/mcp/runtime.js +31 -13
  52. package/build/mcp/{tool-gating.js → toolGating.js} +77 -49
  53. package/build/mcp/{ui-bridge.js → uiBridge.js} +80 -23
  54. package/build/schemas/account-management/account.js +144 -6
  55. package/build/schemas/analytics/analytics.js +33 -19
  56. package/build/schemas/communication/messages.js +12 -42
  57. package/build/schemas/developer/developer.js +135 -0
  58. package/build/schemas/fulfillment/orders.js +183 -21
  59. package/build/schemas/index.js +27 -19
  60. package/build/schemas/inventory-management/inventory.js +17 -9
  61. package/build/schemas/marketing/marketing.js +480 -25
  62. package/build/schemas/metadata/metadata.js +11 -6
  63. package/build/schemas/other/finding.js +27 -0
  64. package/build/schemas/other/otherApis.js +424 -0
  65. package/build/schemas/taxonomy/taxonomy.js +11 -5
  66. package/build/scripts/{auto-setup.js → autoSetup.js} +87 -74
  67. package/build/scripts/{build-ui.js → buildUi.js} +6 -1
  68. package/build/scripts/{dev-sync.js → devSync.js} +169 -110
  69. package/build/scripts/diagnostics.js +52 -44
  70. package/build/scripts/{download-specs.js → downloadSpecs.js} +29 -21
  71. package/build/scripts/{interactive-setup.js → interactiveSetup.js} +84 -78
  72. package/build/scripts/setup.js +241 -178
  73. package/build/scripts/{setup-shared.js → setupShared.js} +29 -7
  74. package/build/scripts/skills.js +35 -27
  75. package/build/scripts/updateApiStatusDoc.js +71 -0
  76. package/build/serverHttp.js +90 -0
  77. package/build/skills/content.js +124 -118
  78. package/build/skills/index.js +22 -10
  79. package/build/skills/install.js +21 -10
  80. package/build/skills/markers.js +50 -15
  81. package/build/skills/{registry-snapshot.js → registrySnapshot.js} +8 -2
  82. package/build/skills/render.js +41 -14
  83. package/build/skills/targets.js +49 -17
  84. package/build/tools/categories/account.js +166 -264
  85. package/build/tools/categories/analytics.js +11 -22
  86. package/build/tools/categories/browse.js +17 -0
  87. package/build/tools/categories/communication.js +124 -399
  88. package/build/tools/categories/connector.js +23 -20
  89. package/build/tools/categories/developer.js +46 -159
  90. package/build/tools/categories/fulfillment.js +84 -215
  91. package/build/tools/categories/index.js +6 -14
  92. package/build/tools/categories/inventory.js +238 -293
  93. package/build/tools/categories/marketing.js +677 -39
  94. package/build/tools/categories/metadata.js +190 -117
  95. package/build/tools/categories/other.js +81 -208
  96. package/build/tools/categories/taxonomy.js +29 -20
  97. package/build/tools/categories/{token-management.js → tokenManagement.js} +187 -192
  98. package/build/tools/categories/trading.js +16 -47
  99. package/build/tools/contracts.js +34 -24
  100. package/build/tools/{define-tool.js → defineTool.js} +44 -29
  101. package/build/tools/registry.js +87 -29
  102. package/build/tools/schemas.js +3 -57
  103. package/build/tools/ui/archetypes.js +1 -0
  104. package/build/tools/ui/{map-helpers.js → mapHelpers.js} +69 -19
  105. package/build/tools/ui/maps.js +294 -80
  106. package/build/types/index.js +1 -1
  107. package/build/ui/card.html +14 -14
  108. package/build/ui/chart.html +14 -14
  109. package/build/ui/stat.html +87 -0
  110. package/build/ui/table.html +14 -14
  111. package/build/utils/apiStatusFeed.js +95 -0
  112. package/build/utils/cliOutput.js +15 -0
  113. package/build/utils/cliUi.js +108 -0
  114. package/build/utils/communication/feedback.js +57 -77
  115. package/build/utils/communication/message.js +69 -98
  116. package/build/utils/communication/negotiation.js +30 -57
  117. package/build/utils/communication/notification.js +112 -252
  118. package/build/utils/{date-converter.js → dateConverter.js} +62 -30
  119. package/build/utils/effectSchema.js +203 -0
  120. package/build/utils/effectSchemaAdapter.js +121 -0
  121. package/build/utils/effectSchemaChainMethods.js +146 -0
  122. package/build/utils/effectSchemaRefinements.js +104 -0
  123. package/build/utils/effectSchemaStringMethods.js +63 -0
  124. package/build/utils/effectSchemaTypes.js +47 -0
  125. package/build/utils/{env-parser.js → envParser.js} +10 -2
  126. package/build/utils/errors.js +7 -3
  127. package/build/utils/http.js +148 -89
  128. package/build/utils/{llm-client-detector.js → llmClientDetector.js} +295 -274
  129. package/build/utils/logger.js +127 -51
  130. package/build/utils/{oauth-helper.js → oauthHelper.js} +127 -90
  131. package/build/utils/other/compliance.js +18 -38
  132. package/build/utils/other/identity.js +2 -2
  133. package/build/utils/other/translation.js +4 -4
  134. package/build/utils/other/vero.js +36 -20
  135. package/build/utils/schemaHelpers.js +22 -0
  136. package/build/utils/scopeHelper.js +270 -0
  137. package/build/utils/securityChecker.js +316 -0
  138. package/build/utils/{setup-validator.js → setupValidator.js} +113 -94
  139. package/build/utils/{setup-wizard.js → setupWizard.js} +57 -46
  140. package/build/utils/{token-utils.js → tokenUtils.js} +2 -2
  141. package/build/utils/trading/trading.js +35 -0
  142. package/build/utils/typeGuards.js +12 -0
  143. package/build/utils/version.js +65 -29
  144. package/package.json +10 -8
  145. package/build/api/client-trading.js +0 -124
  146. package/build/api/communication/shared.js +0 -59
  147. package/build/api/shared/query-params.js +0 -16
  148. package/build/auth/credential-session.js +0 -166
  149. package/build/auth/oauth-middleware.js +0 -100
  150. package/build/auth/token-verifier.js +0 -186
  151. package/build/schemas/other/other-apis.js +0 -390
  152. package/build/scripts/update-api-status-doc.js +0 -44
  153. package/build/server-http.js +0 -85
  154. package/build/tools/definitions/marketing.js +0 -1381
  155. package/build/tools/tool-handlers/marketing.js +0 -312
  156. package/build/utils/account-management/account.js +0 -818
  157. package/build/utils/api-status-feed.js +0 -84
  158. package/build/utils/cli-ui.js +0 -47
  159. package/build/utils/order-management/dispute.js +0 -369
  160. package/build/utils/order-management/fulfillment.js +0 -205
  161. package/build/utils/other/edelivery.js +0 -235
  162. package/build/utils/schema-helpers.js +0 -13
  163. package/build/utils/scope-helper.js +0 -207
  164. package/build/utils/security-checker.js +0 -248
  165. package/build/utils/type-guards.js +0 -6
  166. /package/build/auth/{oauth-types.js → oauthTypes.js} +0 -0
  167. /package/build/{server-http.d.ts → serverHttp.d.ts} +0 -0
  168. /package/build/tools/ui/{view-models.js → viewModels.js} +0 -0
  169. /package/build/types/{ebay-enums.js → ebayEnums.js} +0 -0
@@ -1,26 +1,36 @@
1
1
  import { getToolEntries } from '../tools/registry.js';
2
- function isJsonObject(value) {
3
- return typeof value === 'object' && value !== null && !Array.isArray(value);
4
- }
5
- /** Builds public tool contracts from the validated tool registry entries. */
6
- export function getToolContracts() {
7
- return getToolEntries().map(({ definition }) => ({
8
- annotations: definition.annotations,
9
- description: definition.description,
10
- name: definition.name,
11
- inputSchema: definition.inputSchema,
12
- outputSchema: definition.outputSchema,
13
- title: definition.title,
14
- }));
15
- }
16
- function isZodLikeSchema(schema) {
17
- return (typeof schema === 'object' &&
18
- schema !== null &&
19
- 'safeParse' in schema &&
20
- typeof schema.safeParse === 'function');
21
- }
22
- /** Validates tool contracts for unique names, descriptions, input schemas, and output schemas. */
23
- export function validateToolContracts(contracts = getToolContracts()) {
2
+ import { isEffectBackedSchema } from '../utils/effectSchema.js';
3
+ const isJsonObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
4
+ /**
5
+ * Builds public tool contracts from the validated tool registry entries.
6
+ *
7
+ * @returns Normalized tool contracts in registry execution order.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * const contracts = getToolContracts();
12
+ * ```
13
+ */
14
+ export const getToolContracts = () => getToolEntries().map(({ definition }) => ({
15
+ annotations: definition.annotations,
16
+ description: definition.description,
17
+ name: definition.name,
18
+ inputSchema: definition.inputSchema,
19
+ outputSchema: definition.outputSchema,
20
+ title: definition.title,
21
+ }));
22
+ /**
23
+ * Validates tool contracts for unique names, descriptions, input schemas, and output schemas.
24
+ *
25
+ * @param contracts - Contracts to validate, defaulting to the current registry projection.
26
+ * @returns Duplicate names and malformed contract fields grouped by failure type.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * const validation = validateToolContracts(getToolContracts());
31
+ * ```
32
+ */
33
+ export const validateToolContracts = (contracts = getToolContracts()) => {
24
34
  const seenNames = new Set();
25
35
  const duplicateContracts = new Set();
26
36
  const invalidInputSchemaFields = [];
@@ -37,7 +47,7 @@ export function validateToolContracts(contracts = getToolContracts()) {
37
47
  }
38
48
  else {
39
49
  for (const [fieldName, schema] of Object.entries(contract.inputSchema)) {
40
- if (!isZodLikeSchema(schema)) {
50
+ if (!isEffectBackedSchema(schema)) {
41
51
  invalidInputSchemaFields.push(`${contract.name}.${fieldName}`);
42
52
  }
43
53
  }
@@ -66,4 +76,4 @@ export function validateToolContracts(contracts = getToolContracts()) {
66
76
  missingDescriptions: missingDescriptions.sort(),
67
77
  missingInputSchemas: missingInputSchemas.sort(),
68
78
  };
69
- }
79
+ };
@@ -1,5 +1,5 @@
1
- import { z } from 'zod';
2
1
  import { uiArchetypes } from '../tools/ui/archetypes.js';
2
+ import { decodeEffectSchemaSync, z } from '../utils/effectSchema.js';
3
3
  /**
4
4
  * Erases the compile-time result type from a {@link ToolUiSpec} so the binding can
5
5
  * live on the non-generic {@link ToolEntry}, and resolves the archetype's
@@ -16,28 +16,7 @@ function resolveToolUi(ui) {
16
16
  map: (result) => ui.map(result),
17
17
  };
18
18
  }
19
- /**
20
- * Binds a tool's Zod input shape to its handler so the shape is the single
21
- * source of truth for both the advertised MCP schema and the handler's
22
- * compile-time argument types.
23
- *
24
- * The returned {@link ToolEntry} carries a `ToolHandler` that validates raw
25
- * arguments against the shape before delegating, which gives the codebase two
26
- * properties it lacked while definitions and handlers lived in separate trees
27
- * joined by a string key:
28
- *
29
- * - **Drift is a compile error.** The handler can only read fields the shape
30
- * declares, with their declared types — a renamed field or changed type fails
31
- * `tsc` instead of surfacing at runtime, and the per-handler `as` casts
32
- * disappear.
33
- * - **One validation path.** Both the MCP SDK transport and the registry's
34
- * `executeTool` (used by tests) run the same parse, so tests exercise the
35
- * validation production actually performs.
36
- *
37
- * Re-validating on the SDK path (which already parsed the args) is intentional
38
- * and cheap: the input schemas contain no `.transform()` or async refinements,
39
- * so the second parse is idempotent.
40
- */
19
+ /** Builds the public MCP definition from the richer tool spec. */
41
20
  function toDefinition(spec) {
42
21
  return {
43
22
  name: spec.name,
@@ -49,18 +28,41 @@ function toDefinition(spec) {
49
28
  _meta: spec._meta,
50
29
  };
51
30
  }
52
- export function defineTool(spec) {
31
+ /**
32
+ * Binds a tool's Effect-backed input shape to its handler so the shape is the single
33
+ * source of truth for both the advertised MCP schema and the handler's
34
+ * compile-time argument types.
35
+ *
36
+ * The returned {@link ToolEntry} carries a `ToolHandler` that validates raw
37
+ * arguments against the Effect schema before delegating. Re-validating on the
38
+ * SDK path is intentional and cheap: input schemas contain no async refinements,
39
+ * so the second decode is idempotent.
40
+ *
41
+ * @param spec - Tool definition, input schema, handler, and optional UI projection.
42
+ * @returns A registry entry whose handler validates args from the schema before execution.
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * const entry = defineTool({
47
+ * name: 'ebay_get_custom_policies',
48
+ * description: 'Retrieve custom policies defined for the seller account',
49
+ * inputSchema: getCustomPoliciesInputSchema.shape,
50
+ * handler: (api, args) => Effect.runPromise(api.account.getCustomPolicies(args)),
51
+ * });
52
+ * ```
53
+ */
54
+ export const defineTool = (spec) => {
53
55
  const schema = z.object(spec.inputSchema);
54
- // Non-async: `schema.parse` runs synchronously so invalid input rejects via
56
+ // Non-async: Effect decode runs synchronously so invalid input rejects via
55
57
  // the caller's `await`, and the handler's returned promise passes straight
56
58
  // through without an extra await layer.
57
- const handler = (api, args) => spec.handler(api, schema.parse(args));
59
+ const handler = (api, args) => spec.handler(api, decodeEffectSchemaSync(schema, args));
58
60
  return {
59
61
  definition: toDefinition(spec),
60
62
  handler,
61
63
  ui: spec.ui ? resolveToolUi(spec.ui) : undefined,
62
64
  };
63
- }
65
+ };
64
66
  /**
65
67
  * Like {@link defineTool}, but invokes the handler with the raw transport
66
68
  * arguments WITHOUT re-validating them against `inputSchema`.
@@ -75,12 +77,25 @@ export function defineTool(spec) {
75
77
  *
76
78
  * `args` is typed from the shape for handler ergonomics, but the values are not
77
79
  * validated by this factory — the handler is responsible for that.
80
+ *
81
+ * @param spec - Tool definition, advertised input schema, raw handler, and optional UI projection.
82
+ * @returns A registry entry whose handler receives raw transport args.
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * const entry = rawTool({
87
+ * name: 'ebay_send_message',
88
+ * description: 'Send a member message',
89
+ * inputSchema: advertisedMessageShape,
90
+ * handler: (api, args) => api.message.sendMessage(args),
91
+ * });
92
+ * ```
78
93
  */
79
- export function rawTool(spec) {
94
+ export const rawTool = (spec) => {
80
95
  const handler = (api, args) => spec.handler(api, args);
81
96
  return {
82
97
  definition: toDefinition(spec),
83
98
  handler,
84
99
  ui: spec.ui ? resolveToolUi(spec.ui) : undefined,
85
100
  };
86
- }
101
+ };
@@ -1,12 +1,25 @@
1
- import { handlerOnlyEntries, registeredEntries } from '../tools/categories/index.js';
2
- /** Handler lookup keyed by tool name, including handler-only (unadvertised) tools. */
3
- const handlerByName = Object.fromEntries([...registeredEntries, ...handlerOnlyEntries].map((entry) => [
4
- entry.definition.name,
5
- entry.handler,
6
- ]));
1
+ import { registeredEntries } from '../tools/categories/index.js';
2
+ import { Data, Effect } from 'effect';
3
+ /** Tagged failure returned when the tool registry cannot resolve a runnable tool. */
4
+ export class ToolRegistryError extends Data.TaggedError('ToolRegistryError') {
5
+ }
6
+ /** Handler lookup keyed by registered public tool name. */
7
+ const handlerByName = Object.fromEntries(registeredEntries.map((entry) => [entry.definition.name, entry.handler]));
7
8
  let cachedEntries;
8
- /** Validates that tool definitions have unique names and matching handlers. */
9
- export function validateToolRegistry(definitions = registeredEntries.map((entry) => entry.definition), handlers = handlerByName) {
9
+ /**
10
+ * Validates that tool definitions have unique names and matching handlers.
11
+ *
12
+ * @param definitions - Public tool definitions to validate, defaulting to registered tools.
13
+ * @param handlers - Handler lookup used to verify every definition can execute.
14
+ * @returns Duplicate definition names plus missing or orphaned handlers.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * const validation = validateToolRegistry();
19
+ * const hasDuplicates = validation.duplicateToolNames.length > 0;
20
+ * ```
21
+ */
22
+ export const validateToolRegistry = (definitions = registeredEntries.map((entry) => entry.definition), handlers = handlerByName) => {
10
23
  const seenNames = new Set();
11
24
  const duplicateNames = new Set();
12
25
  for (const definition of definitions) {
@@ -24,8 +37,8 @@ export function validateToolRegistry(definitions = registeredEntries.map((entry)
24
37
  .sort(),
25
38
  orphanHandlers: [...handlerNames].filter((name) => !seenNames.has(name)).sort(),
26
39
  };
27
- }
28
- function assertRunnableRegistry() {
40
+ };
41
+ const validateRunnableRegistry = () => {
29
42
  const validation = validateToolRegistry();
30
43
  const failures = [
31
44
  validation.duplicateToolNames.length > 0
@@ -36,31 +49,76 @@ function assertRunnableRegistry() {
36
49
  : undefined,
37
50
  ].filter(Boolean);
38
51
  if (failures.length > 0) {
39
- throw new Error(`Invalid tool registry: ${failures.join('; ')}`);
52
+ return Effect.fail(new ToolRegistryError({
53
+ message: `Invalid tool registry: ${failures.join('; ')}`,
54
+ }));
40
55
  }
41
- }
42
- /** Returns cached runnable registry entries after validating definitions and handlers. */
43
- export function getToolEntries() {
56
+ return Effect.void;
57
+ };
58
+ /**
59
+ * Returns cached runnable registry entries after validating definitions and handlers.
60
+ *
61
+ * @returns Registered tool entries in execution order.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * const entries = getToolEntries();
66
+ * ```
67
+ */
68
+ export const getToolEntries = () => {
44
69
  if (cachedEntries) {
45
70
  return cachedEntries;
46
71
  }
47
- assertRunnableRegistry();
72
+ Effect.runSync(validateRunnableRegistry());
48
73
  cachedEntries = registeredEntries;
49
74
  return cachedEntries;
50
- }
51
- /** Returns public tool definitions in registry execution order. */
52
- export function getToolDefinitions() {
53
- return getToolEntries().map((entry) => entry.definition);
54
- }
55
- /** Looks up the handler registered for a tool name, if one exists. */
56
- export function getToolHandler(toolName) {
57
- return handlerByName[toolName];
58
- }
59
- /** Executes a registered tool handler or throws when the tool name is unknown. */
60
- export async function executeTool(api, toolName, args) {
75
+ };
76
+ /**
77
+ * Returns public tool definitions in registry execution order.
78
+ *
79
+ * @returns MCP tool definitions advertised to clients.
80
+ *
81
+ * @example
82
+ * ```ts
83
+ * const definitions = getToolDefinitions();
84
+ * ```
85
+ */
86
+ export const getToolDefinitions = () => getToolEntries().map((entry) => entry.definition);
87
+ /**
88
+ * Looks up the handler registered for a tool name, if one exists.
89
+ *
90
+ * @param toolName - MCP tool name to resolve.
91
+ * @returns The registered handler, or undefined when the name is unknown.
92
+ *
93
+ * @example
94
+ * ```ts
95
+ * const handler = getToolHandler('ebay_get_custom_policies');
96
+ * ```
97
+ */
98
+ export const getToolHandler = (toolName) => handlerByName[toolName];
99
+ /**
100
+ * Executes a registered tool handler and rejects when the tool name is unknown.
101
+ *
102
+ * @param api - eBay API facade passed to the selected tool handler.
103
+ * @param toolName - MCP tool name to execute.
104
+ * @param args - Raw transport arguments parsed by the selected tool entry.
105
+ * @returns The selected handler's result.
106
+ *
107
+ * @example
108
+ * ```ts
109
+ * const result = await executeTool(api, 'ebay_get_custom_policies', {});
110
+ * ```
111
+ */
112
+ export const executeTool = async (api, toolName, args) => Effect.runPromise(Effect.gen(function* () {
61
113
  const handler = getToolHandler(toolName);
62
114
  if (!handler) {
63
- throw new Error(`Unknown tool: ${toolName}`);
115
+ return yield* Effect.fail(new ToolRegistryError({
116
+ message: `Unknown tool: ${toolName}`,
117
+ toolName,
118
+ }));
64
119
  }
65
- return await handler(api, args);
66
- }
120
+ return yield* Effect.tryPromise({
121
+ try: () => Promise.resolve(handler(api, args)),
122
+ catch: (error) => error,
123
+ });
124
+ }));
@@ -1,7 +1,7 @@
1
- import { z } from 'zod';
2
- import { TimeDurationUnit, RegionType, ShippingCostType, ShippingOptionType, DepositType, RefundMethod, ReturnMethod, ReturnShippingCostPayer, Condition, LengthUnit, WeightUnit, PricingVisibility, FormatType, LocationType, MerchantLocationStatus, DayOfWeek, ReasonForRefund, FundingModel, MessageReferenceType, FeedbackRating, ReportedItemType, } from '../types/ebay-enums.js';
1
+ import { z } from '../utils/effectSchema.js';
2
+ import { TimeDurationUnit, RegionType, ShippingCostType, ShippingOptionType, DepositType, RefundMethod, ReturnMethod, ReturnShippingCostPayer, Condition, LengthUnit, WeightUnit, PricingVisibility, FormatType, LocationType, MerchantLocationStatus, DayOfWeek, ReasonForRefund, FundingModel, MessageReferenceType, FeedbackRating, ReportedItemType, } from '../types/ebayEnums.js';
3
3
  /**
4
- * Reusable Zod schemas for eBay API tool input validation
4
+ * Reusable Effect-backed schemas for eBay API tool input validation
5
5
  *
6
6
  * These schemas provide type-safe validation while remaining flexible
7
7
  * enough to accept the full complexity of eBay API request objects.
@@ -556,60 +556,6 @@ export const infringementDataSchema = z
556
556
  comments: z.string().optional(),
557
557
  })
558
558
  .passthrough();
559
- // VERO API schemas
560
- /** VeRO report payload for intellectual-property violation submissions. */
561
- export const veroReportDataSchema = z
562
- .object({
563
- items: z.array(z.object({
564
- itemId: z.string(),
565
- reportingReason: z.string(),
566
- })),
567
- rightsOwnerEmail: z.string().email().optional(),
568
- message: z.string().optional(),
569
- })
570
- .passthrough();
571
- /** Shipping quote request payload for estimated shipping rates. */
572
- export const shippingQuoteRequestSchema = z
573
- .object({
574
- packageDetails: z
575
- .object({
576
- weight: z
577
- .object({
578
- value: z.number(),
579
- unit: z.string(),
580
- })
581
- .passthrough(),
582
- dimensions: z
583
- .object({
584
- height: z.number().optional(),
585
- length: z.number().optional(),
586
- width: z.number().optional(),
587
- unit: z.string().optional(),
588
- })
589
- .passthrough()
590
- .optional(),
591
- })
592
- .passthrough(),
593
- shipFrom: z
594
- .object({
595
- addressLine1: z.string().optional(),
596
- city: z.string().optional(),
597
- stateOrProvince: z.string().optional(),
598
- postalCode: z.string().optional(),
599
- country: z.string(),
600
- })
601
- .passthrough(),
602
- shipTo: z
603
- .object({
604
- addressLine1: z.string().optional(),
605
- city: z.string().optional(),
606
- stateOrProvince: z.string().optional(),
607
- postalCode: z.string().optional(),
608
- country: z.string(),
609
- })
610
- .passthrough(),
611
- })
612
- .passthrough();
613
559
  // ============================================================================
614
560
  // Bulk Operation Schemas
615
561
  // ============================================================================
@@ -8,4 +8,5 @@ export const uiArchetypes = {
8
8
  table: { uri: 'ui://ebay/table.html', name: 'eBay table view', htmlFile: 'table.html' },
9
9
  card: { uri: 'ui://ebay/card.html', name: 'eBay detail card view', htmlFile: 'card.html' },
10
10
  chart: { uri: 'ui://ebay/chart.html', name: 'eBay chart view', htmlFile: 'chart.html' },
11
+ stat: { uri: 'ui://ebay/stat.html', name: 'eBay stat grid view', htmlFile: 'stat.html' },
11
12
  };
@@ -12,35 +12,59 @@
12
12
  * Renders an eBay money object as `"<value> <currency>"` (e.g. `"25.99 USD"`),
13
13
  * or just the value when no currency is present. Returns `null` for a missing
14
14
  * amount so callers can drop it straight into a nullable cell or field.
15
+ *
16
+ * @param amount - eBay amount-like object from a generated response.
17
+ * @returns A display string with currency, or null when the amount is missing.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * formatAmount({ value: '25.99', currency: 'USD' });
22
+ * ```
15
23
  */
16
- export function formatAmount(amount) {
24
+ export const formatAmount = (amount) => {
17
25
  if (amount?.value == null) {
18
26
  return null;
19
27
  }
20
28
  return amount.currency ? `${amount.value} ${amount.currency}` : amount.value;
21
- }
29
+ };
22
30
  /**
23
31
  * Turns eBay's `SCREAMING_SNAKE_CASE` status codes into human-readable sentence
24
32
  * case (`"ITEM_NOT_RECEIVED"` → `"Item not received"`): underscores become
25
33
  * spaces and only the first word is capitalised, which reads more naturally for
26
- * multi-word statuses than Title Case. Returns an em dash for a missing status
27
- * so tables and cards never render a blank cell.
34
+ * multi-word statuses than Title Case. Returns `null` for a missing status so
35
+ * the React view, not the mapper, owns placeholder rendering.
36
+ *
37
+ * @param status - Optional eBay enum/status value.
38
+ * @returns A display label, or null when no status was provided.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * humanizeStatus('ITEM_NOT_RECEIVED');
43
+ * ```
28
44
  */
29
- export function humanizeStatus(status) {
45
+ export const humanizeStatus = (status) => {
30
46
  if (!status) {
31
- return '—';
47
+ return null;
32
48
  }
33
49
  const lowered = status.toLowerCase().replace(/_/g, ' ');
34
50
  return lowered.charAt(0).toUpperCase() + lowered.slice(1);
35
- }
51
+ };
36
52
  /**
37
53
  * Maps a status code to a {@link CardBadge} tone so detail cards can colour
38
54
  * their state pills. Unknown or terminal-neutral statuses fall back to
39
55
  * `'neutral'`. The buckets are intentionally broad keyword matches rather than
40
56
  * an exhaustive enum — new eBay statuses degrade to neutral, never to a wrong
41
57
  * colour-implied meaning.
58
+ *
59
+ * @param status - Optional eBay enum/status value.
60
+ * @returns Badge tone used by card view models.
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * statusTone('FULFILLED');
65
+ * ```
42
66
  */
43
- export function statusTone(status) {
67
+ export const statusTone = (status) => {
44
68
  if (!status) {
45
69
  return 'neutral';
46
70
  }
@@ -55,27 +79,44 @@ export function statusTone(status) {
55
79
  return 'success';
56
80
  }
57
81
  return 'neutral';
58
- }
82
+ };
59
83
  /**
60
84
  * Coerces an untyped JSON leaf (the analytics specs type report values as
61
85
  * `Record<string, never>`, though at runtime they are numbers or numeric
62
- * strings) to a finite number, defaulting to `0`. Used for chart Y values.
86
+ * strings) to a finite number. Missing or invalid values return `null` so chart
87
+ * mappers can omit the point instead of inventing a zero.
88
+ *
89
+ * @param value - Analytics value leaf from an eBay report response.
90
+ * @returns A finite number for chart points, or null for non-numeric input.
91
+ *
92
+ * @example
93
+ * ```ts
94
+ * toNumber('42');
95
+ * ```
63
96
  */
64
- export function toNumber(value) {
97
+ export const toNumber = (value) => {
65
98
  if (typeof value === 'number') {
66
- return Number.isFinite(value) ? value : 0;
99
+ return Number.isFinite(value) ? value : null;
67
100
  }
68
101
  if (typeof value === 'string') {
69
102
  const parsed = Number(value);
70
- return Number.isFinite(parsed) ? parsed : 0;
103
+ return Number.isFinite(parsed) ? parsed : null;
71
104
  }
72
- return 0;
73
- }
105
+ return null;
106
+ };
74
107
  /**
75
108
  * Coerces an untyped JSON leaf to a chart-axis label string, returning `''` for
76
109
  * values that have no sensible textual form (objects, `null`, `undefined`).
110
+ *
111
+ * @param value - Analytics dimension leaf from an eBay report response.
112
+ * @returns A primitive label string, or an empty string when no label is available.
113
+ *
114
+ * @example
115
+ * ```ts
116
+ * toLabel(7);
117
+ * ```
77
118
  */
78
- export function toLabel(value) {
119
+ export const toLabel = (value) => {
79
120
  if (typeof value === 'string') {
80
121
  return value;
81
122
  }
@@ -83,15 +124,24 @@ export function toLabel(value) {
83
124
  return String(value);
84
125
  }
85
126
  return '';
86
- }
127
+ };
87
128
  /**
88
129
  * Shortens free-text (product descriptions, titles) to `max` characters with a
89
130
  * trailing ellipsis, so a table cell or card field stays one line. Returns `''`
90
131
  * for missing text.
132
+ *
133
+ * @param text - Optional free-text value from an eBay response.
134
+ * @param max - Maximum display length including the ellipsis.
135
+ * @returns Truncated text, original text, or an empty string when text is missing.
136
+ *
137
+ * @example
138
+ * ```ts
139
+ * truncate('A long product title', 12);
140
+ * ```
91
141
  */
92
- export function truncate(text, max = 80) {
142
+ export const truncate = (text, max = 80) => {
93
143
  if (!text) {
94
144
  return '';
95
145
  }
96
146
  return text.length > max ? `${text.slice(0, max - 1)}…` : text;
97
- }
147
+ };