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,10 +1,10 @@
1
- import { buildRegistrySnapshot } from '../skills/registry-snapshot.js';
1
+ import { buildRegistrySnapshot } from '../skills/registrySnapshot.js';
2
2
  import { buildContributingDoc, buildUsingDoc } from '../skills/content.js';
3
3
  import { renderSkill } from '../skills/render.js';
4
4
  import { resolveTargets } from '../skills/targets.js';
5
5
  import { planWrite } from '../skills/install.js';
6
6
  export * from '../skills/types.js';
7
- export { buildRegistrySnapshot } from '../skills/registry-snapshot.js';
7
+ export { buildRegistrySnapshot } from '../skills/registrySnapshot.js';
8
8
  export { buildUsingDoc, buildContributingDoc } from '../skills/content.js';
9
9
  export { renderSkill, renderClaudeSkill, renderCursorRule, renderCodexSection, } from '../skills/render.js';
10
10
  export { ALL_PROVIDERS, providerLabel, supportsScope, detectProvider, resolveTargets, } from '../skills/targets.js';
@@ -14,10 +14,14 @@ export { planWrite, applyWrite } from '../skills/install.js';
14
14
  *
15
15
  * @param layer Which audience the skill serves.
16
16
  * @param snapshot Live registry snapshot (defaults to a fresh one).
17
+ * @returns Provider-neutral skill document for the requested layer.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * const doc = buildSkillDoc('using');
22
+ * ```
17
23
  */
18
- export function buildSkillDoc(layer, snapshot = buildRegistrySnapshot()) {
19
- return layer === 'using' ? buildUsingDoc(snapshot) : buildContributingDoc(snapshot);
20
- }
24
+ export const buildSkillDoc = (layer, snapshot = buildRegistrySnapshot()) => (layer === 'using' ? buildUsingDoc(snapshot) : buildContributingDoc(snapshot));
21
25
  /**
22
26
  * The end-to-end core: resolves targets for the chosen providers × layers,
23
27
  * renders each into its provider's native format, and returns idempotent write
@@ -25,8 +29,13 @@ export function buildSkillDoc(layer, snapshot = buildRegistrySnapshot()) {
25
29
  *
26
30
  * @param options Providers, layers, scope, and optional cwd/home/snapshot overrides.
27
31
  * @returns One {@link RenderedTarget} per provider/layer target.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * const rendered = renderSkillTargets({ providers: ['codex'], layers: ['using'], scope: 'project' });
36
+ * ```
28
37
  */
29
- export function renderSkillTargets(options) {
38
+ export const renderSkillTargets = (options) => {
30
39
  const snapshot = options.snapshot ?? buildRegistrySnapshot();
31
40
  const docByLayer = {
32
41
  using: buildUsingDoc(snapshot),
@@ -37,7 +46,7 @@ export function renderSkillTargets(options) {
37
46
  target,
38
47
  payload: renderSkill(target.provider, docByLayer[target.layer], target.layer),
39
48
  }));
40
- }
49
+ };
41
50
  /**
42
51
  * Builds preview write plans for the chosen providers × layers. Note: when two
43
52
  * managed-block targets share a file (both Codex layers → one `AGENTS.md`), each
@@ -48,7 +57,10 @@ export function renderSkillTargets(options) {
48
57
  *
49
58
  * @param options Providers, layers, scope, and optional cwd/home/snapshot overrides.
50
59
  * @returns One {@link WritePlan} per provider/layer target.
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * const plans = buildSkillPlans({ providers: ['codex'], layers: ['using'], scope: 'project' });
64
+ * ```
51
65
  */
52
- export function buildSkillPlans(options) {
53
- return renderSkillTargets(options).map((rendered) => planWrite(rendered.target, rendered.payload));
54
- }
66
+ export const buildSkillPlans = (options) => renderSkillTargets(options).map((rendered) => planWrite(rendered.target, rendered.payload));
@@ -2,15 +2,13 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
2
2
  import { dirname } from 'path';
3
3
  import { blockEnd, blockStart, isOwnedByUs } from '../skills/markers.js';
4
4
  /** Wraps managed-block inner content between this layer's delimiters. */
5
- function wrapBlock(layer, inner) {
6
- return `${blockStart(layer)}\n${inner}\n${blockEnd(layer)}`;
7
- }
5
+ const wrapBlock = (layer, inner) => `${blockStart(layer)}\n${inner}\n${blockEnd(layer)}`;
8
6
  /**
9
7
  * Replaces our managed block in `existing`, or appends it if absent — preserving
10
8
  * all surrounding user content. Idempotent: feeding the result back in produces
11
9
  * identical output.
12
10
  */
13
- function mergeManagedBlock(existing, layer, inner) {
11
+ const mergeManagedBlock = (existing, layer, inner) => {
14
12
  const start = blockStart(layer);
15
13
  const end = blockEnd(layer);
16
14
  const block = wrapBlock(layer, inner);
@@ -21,7 +19,7 @@ function mergeManagedBlock(existing, layer, inner) {
21
19
  }
22
20
  const prefix = existing.trim().length > 0 ? `${existing.replace(/\s+$/, '')}\n\n` : '';
23
21
  return `${prefix}${block}\n`;
24
- }
22
+ };
25
23
  /**
26
24
  * Computes what a write would do without touching disk.
27
25
  *
@@ -35,13 +33,21 @@ function mergeManagedBlock(existing, layer, inner) {
35
33
  * @param payload Rendered content — a full file for owned targets, inner block
36
34
  * content for managed targets.
37
35
  * @returns The planned action and the exact bytes that would be written.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * const plan = planWrite(target, payload);
40
+ * ```
38
41
  */
39
- export function planWrite(target, payload) {
42
+ export const planWrite = (target, payload) => {
40
43
  const exists = existsSync(target.path);
41
44
  const previousContents = exists ? readFileSync(target.path, 'utf-8') : undefined;
42
45
  if (target.kind === 'managed-block') {
43
46
  const nextContents = mergeManagedBlock(previousContents ?? '', target.layer, payload);
44
- const action = !exists ? 'create' : nextContents === previousContents ? 'unchanged' : 'update';
47
+ let action = 'create';
48
+ if (exists) {
49
+ action = nextContents === previousContents ? 'unchanged' : 'update';
50
+ }
45
51
  return { target, action, nextContents, previousContents };
46
52
  }
47
53
  // owned-file
@@ -53,7 +59,7 @@ export function planWrite(target, payload) {
53
59
  }
54
60
  const action = previousContents === payload ? 'unchanged' : 'update';
55
61
  return { target, action, nextContents: payload, previousContents };
56
- }
62
+ };
57
63
  /**
58
64
  * Applies a write plan. Skips no-op writes (`unchanged`) and refuses to clobber
59
65
  * a foreign owned file unless `force` is set. `dryRun` computes the result
@@ -62,8 +68,13 @@ export function planWrite(target, payload) {
62
68
  * @param plan The plan from {@link planWrite}.
63
69
  * @param options `dryRun` to preview only; `force` to overwrite a foreign file.
64
70
  * @returns Whether the file was written.
71
+ *
72
+ * @example
73
+ * ```ts
74
+ * const result = applyWrite(plan, { dryRun: true });
75
+ * ```
65
76
  */
66
- export function applyWrite(plan, options = {}) {
77
+ export const applyWrite = (plan, options = {}) => {
67
78
  const isNoop = plan.action === 'unchanged';
68
79
  const isBlockedForeign = plan.action === 'skip-foreign' && !options.force;
69
80
  if (options.dryRun || isNoop || isBlockedForeign) {
@@ -72,4 +83,4 @@ export function applyWrite(plan, options = {}) {
72
83
  mkdirSync(dirname(plan.target.path), { recursive: true });
73
84
  writeFileSync(plan.target.path, plan.nextContents, 'utf-8');
74
85
  return { target: plan.target, action: plan.action, written: true };
75
- }
86
+ };
@@ -7,19 +7,54 @@
7
7
  * Markers are HTML comments, which render invisibly in Markdown across all three
8
8
  * tools.
9
9
  */
10
- /** Single-line marker embedded near the top of an owned file to prove ownership. */
11
- export function ownershipMarker(layer) {
12
- return `<!-- ebay-mcp:skill:${layer} (generated — re-run \`ebay-mcp skills\` to update) -->`;
13
- }
14
- /** Opening delimiter of a managed block inside a shared file. */
15
- export function blockStart(layer) {
16
- return `<!-- ebay-mcp:skill:${layer}:start -->`;
17
- }
18
- /** Closing delimiter of a managed block inside a shared file. */
19
- export function blockEnd(layer) {
20
- return `<!-- ebay-mcp:skill:${layer}:end -->`;
21
- }
22
- /** True when file contents already contain content we generated for this layer. */
23
- export function isOwnedByUs(contents, layer) {
10
+ /**
11
+ * Builds the single-line marker embedded near the top of an owned file.
12
+ *
13
+ * @param layer - Skill layer the generated file belongs to.
14
+ * @returns HTML comment proving ownership for this layer.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * const marker = ownershipMarker('using');
19
+ * ```
20
+ */
21
+ export const ownershipMarker = (layer) => `<!-- ebay-mcp:skill:${layer} (generated — re-run \`ebay-mcp skills\` to update) -->`;
22
+ /**
23
+ * Builds the opening delimiter of a managed block inside a shared file.
24
+ *
25
+ * @param layer - Skill layer the managed block belongs to.
26
+ * @returns HTML comment that opens the managed block.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * const start = blockStart('contributing');
31
+ * ```
32
+ */
33
+ export const blockStart = (layer) => `<!-- ebay-mcp:skill:${layer}:start -->`;
34
+ /**
35
+ * Builds the closing delimiter of a managed block inside a shared file.
36
+ *
37
+ * @param layer - Skill layer the managed block belongs to.
38
+ * @returns HTML comment that closes the managed block.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * const end = blockEnd('contributing');
43
+ * ```
44
+ */
45
+ export const blockEnd = (layer) => `<!-- ebay-mcp:skill:${layer}:end -->`;
46
+ /**
47
+ * Checks whether file contents already contain generated content for this layer.
48
+ *
49
+ * @param contents - File contents to inspect.
50
+ * @param layer - Skill layer to look for.
51
+ * @returns True when an ownership marker or managed-block delimiter is present.
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * const ours = isOwnedByUs(contents, 'using');
56
+ * ```
57
+ */
58
+ export const isOwnedByUs = (contents, layer) => {
24
59
  return contents.includes(`ebay-mcp:skill:${layer}`); // matches ownership marker or block delimiters
25
- }
60
+ };
@@ -15,6 +15,7 @@ const FAMILY_BLURBS = {
15
15
  metadata: 'Marketplace policies, item conditions, listing constraints, automotive compatibility',
16
16
  taxonomy: 'Category trees, category suggestions, and required item aspects',
17
17
  communication: 'Buyer messages, member messages, and notification settings',
18
+ browse: 'Sold/completed listing search (Finding API) for pricing comps',
18
19
  other: 'Feedback, recommendations, and assorted Sell-API helpers',
19
20
  developer: 'API status, rate limits, client registration, and signing keys',
20
21
  trading: 'Legacy Trading API (XML) — create / revise / relist / end fixed-price listings',
@@ -25,8 +26,13 @@ const FAMILY_BLURBS = {
25
26
  * (the single source of truth for registry families); blurbs are static copy.
26
27
  *
27
28
  * @returns The current tool count and per-family index, in registry order.
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * const snapshot = buildRegistrySnapshot();
33
+ * ```
28
34
  */
29
- export function buildRegistrySnapshot() {
35
+ export const buildRegistrySnapshot = () => {
30
36
  const families = toolCategories.map((category) => ({
31
37
  key: category.key,
32
38
  title: category.title,
@@ -35,4 +41,4 @@ export function buildRegistrySnapshot() {
35
41
  }));
36
42
  const toolCount = families.reduce((sum, family) => sum + family.count, 0);
37
43
  return { toolCount, families };
38
- }
44
+ };
@@ -5,24 +5,31 @@ import { ownershipMarker } from '../skills/markers.js';
5
5
  * sections) for owned files; level 2 yields an embeddable section (`##` title,
6
6
  * `###` sections) for a managed block inside a user's file.
7
7
  */
8
- function renderBody(doc, baseLevel) {
8
+ const renderBody = (doc, baseLevel) => {
9
9
  const heading = (level) => '#'.repeat(level);
10
10
  const parts = [`${heading(baseLevel)} ${doc.title}`, '', doc.intro];
11
11
  for (const section of doc.sections) {
12
12
  parts.push('', `${heading(baseLevel + 1)} ${section.heading}`, '', section.body);
13
13
  }
14
14
  return parts.join('\n');
15
- }
15
+ };
16
16
  /** YAML frontmatter scalar that is safe for arbitrary text (JSON strings are valid YAML). */
17
- function yamlString(value) {
18
- return JSON.stringify(value);
19
- }
17
+ const yamlString = (value) => JSON.stringify(value);
20
18
  /**
21
19
  * Renders a Claude Code skill file (`SKILL.md`): YAML frontmatter (`name`,
22
20
  * `description`) so the model can invoke it on demand, an ownership marker, then
23
21
  * the shared body.
22
+ *
23
+ * @param doc - Provider-neutral skill document.
24
+ * @param layer - Skill layer used for the ownership marker.
25
+ * @returns Complete Claude Code `SKILL.md` contents.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * const markdown = renderClaudeSkill(doc, 'using');
30
+ * ```
24
31
  */
25
- export function renderClaudeSkill(doc, layer) {
32
+ export const renderClaudeSkill = (doc, layer) => {
26
33
  const frontmatter = [
27
34
  '---',
28
35
  `name: ${doc.slug}`,
@@ -30,13 +37,22 @@ export function renderClaudeSkill(doc, layer) {
30
37
  '---',
31
38
  ];
32
39
  return [...frontmatter, ownershipMarker(layer), '', renderBody(doc, 1), ''].join('\n');
33
- }
40
+ };
34
41
  /**
35
42
  * Renders a Cursor rule file (`.mdc`): frontmatter with a `description` trigger
36
43
  * and `alwaysApply: false` (agent-requested, not file-glob scoped, since eBay
37
44
  * tools aren't tied to particular source files), an ownership marker, then body.
45
+ *
46
+ * @param doc - Provider-neutral skill document.
47
+ * @param layer - Skill layer used for the ownership marker.
48
+ * @returns Complete Cursor `.mdc` rule contents.
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * const markdown = renderCursorRule(doc, 'contributing');
53
+ * ```
38
54
  */
39
- export function renderCursorRule(doc, layer) {
55
+ export const renderCursorRule = (doc, layer) => {
40
56
  const frontmatter = [
41
57
  '---',
42
58
  `description: ${yamlString(doc.description)}`,
@@ -44,15 +60,21 @@ export function renderCursorRule(doc, layer) {
44
60
  '---',
45
61
  ];
46
62
  return [...frontmatter, ownershipMarker(layer), '', renderBody(doc, 1), ''].join('\n');
47
- }
63
+ };
48
64
  /**
49
65
  * Renders the inner content for a Codex `AGENTS.md` managed block: a level-2
50
66
  * section with no frontmatter, so it nests cleanly under a user's existing
51
67
  * top-level heading. The install step wraps this with block delimiters.
68
+ *
69
+ * @param doc - Provider-neutral skill document.
70
+ * @returns Inner Markdown content for a Codex managed block.
71
+ *
72
+ * @example
73
+ * ```ts
74
+ * const section = renderCodexSection(doc);
75
+ * ```
52
76
  */
53
- export function renderCodexSection(doc) {
54
- return renderBody(doc, 2);
55
- }
77
+ export const renderCodexSection = (doc) => renderBody(doc, 2);
56
78
  /**
57
79
  * Renders the payload for one provider. Owned-file providers (Claude, Cursor)
58
80
  * return a complete file; the managed-block provider (Codex) returns inner
@@ -62,8 +84,13 @@ export function renderCodexSection(doc) {
62
84
  * @param doc Canonical skill document.
63
85
  * @param layer Skill layer (for the ownership marker).
64
86
  * @returns The string payload for this provider.
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * const payload = renderSkill('codex', doc, 'using');
91
+ * ```
65
92
  */
66
- export function renderSkill(provider, doc, layer) {
93
+ export const renderSkill = (provider, doc, layer) => {
67
94
  switch (provider) {
68
95
  case 'claude':
69
96
  return renderClaudeSkill(doc, layer);
@@ -72,4 +99,4 @@ export function renderSkill(provider, doc, layer) {
72
99
  case 'codex':
73
100
  return renderCodexSection(doc);
74
101
  }
75
- }
102
+ };
@@ -1,10 +1,21 @@
1
1
  import { existsSync } from 'fs';
2
2
  import { homedir } from 'os';
3
3
  import { join } from 'path';
4
+ import process from 'node:process';
4
5
  /** All providers we can render for, in display order. */
5
6
  export const ALL_PROVIDERS = ['claude', 'cursor', 'codex'];
6
- /** Human label for a provider, used in the wizard and reports. */
7
- export function providerLabel(provider) {
7
+ /**
8
+ * Builds the human label for a provider, used in the wizard and reports.
9
+ *
10
+ * @param provider - Skill provider to label.
11
+ * @returns Display label including the provider's native instruction location.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const label = providerLabel('codex');
16
+ * ```
17
+ */
18
+ export const providerLabel = (provider) => {
8
19
  switch (provider) {
9
20
  case 'claude':
10
21
  return 'Claude Code (.claude/skills)';
@@ -13,22 +24,29 @@ export function providerLabel(provider) {
13
24
  case 'codex':
14
25
  return 'Codex (AGENTS.md)';
15
26
  }
16
- }
27
+ };
17
28
  /**
18
29
  * Whether a provider supports a given scope. Cursor only reads project-local
19
30
  * rule files, so it has no global scope.
31
+ *
32
+ * @param provider - Skill provider being installed.
33
+ * @param scope - Requested install scope.
34
+ * @returns True when the provider can use that scope.
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * const supported = supportsScope('cursor', 'project');
39
+ * ```
20
40
  */
21
- export function supportsScope(provider, scope) {
41
+ export const supportsScope = (provider, scope) => {
22
42
  if (provider === 'cursor')
23
43
  return scope === 'project';
24
44
  return true;
25
- }
45
+ };
26
46
  /** The filename slug for a layer, shared by Claude skill dirs and Cursor rule files. */
27
- function slug(layer) {
28
- return `ebay-mcp-${layer}`;
29
- }
47
+ const slug = (layer) => `ebay-mcp-${layer}`;
30
48
  /** Absolute path of the rendered file for a provider/layer/scope. */
31
- function resolvePath(provider, layer, scope, cwd, home) {
49
+ const resolvePath = (provider, layer, scope, cwd, home) => {
32
50
  const base = scope === 'project' ? cwd : home;
33
51
  switch (provider) {
34
52
  case 'claude':
@@ -38,19 +56,28 @@ function resolvePath(provider, layer, scope, cwd, home) {
38
56
  case 'codex':
39
57
  return scope === 'project' ? join(cwd, 'AGENTS.md') : join(home, '.codex', 'AGENTS.md');
40
58
  }
41
- }
59
+ };
42
60
  /** Codex shares one `AGENTS.md` (managed block); the others own their own file. */
43
- function targetKind(provider) {
44
- return provider === 'codex' ? 'managed-block' : 'owned-file';
45
- }
61
+ const targetKind = (provider) => provider === 'codex' ? 'managed-block' : 'owned-file';
46
62
  /**
47
63
  * Detects whether a provider already has a footprint at this scope, so the
48
64
  * wizard can pre-select the tools a developer actually uses. Looks for the
49
65
  * provider's instruction directory/file rather than the MCP client config —
50
66
  * this is about where agent instructions live, which the MCP detector does not
51
67
  * model.
68
+ *
69
+ * @param provider - Skill provider to detect.
70
+ * @param scope - Install scope to inspect.
71
+ * @param cwd - Project root path.
72
+ * @param home - User home path.
73
+ * @returns True when the provider has a footprint at that scope.
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * const detected = detectProvider('claude', 'project', cwd, home);
78
+ * ```
52
79
  */
53
- export function detectProvider(provider, scope, cwd, home) {
80
+ export const detectProvider = (provider, scope, cwd, home) => {
54
81
  switch (provider) {
55
82
  case 'claude':
56
83
  return existsSync(join(scope === 'project' ? cwd : home, '.claude'));
@@ -61,7 +88,7 @@ export function detectProvider(provider, scope, cwd, home) {
61
88
  ? existsSync(join(cwd, 'AGENTS.md'))
62
89
  : existsSync(join(home, '.codex'));
63
90
  }
64
- }
91
+ };
65
92
  /**
66
93
  * Resolves the concrete write targets for the chosen providers × layers at a
67
94
  * scope. Cursor is coerced to project scope (it has no global rules), so it is
@@ -73,8 +100,13 @@ export function detectProvider(provider, scope, cwd, home) {
73
100
  * @param cwd Project root (defaults to `process.cwd()`).
74
101
  * @param home User home (defaults to `os.homedir()`).
75
102
  * @returns One {@link SkillTarget} per provider/layer.
103
+ *
104
+ * @example
105
+ * ```ts
106
+ * const targets = resolveTargets(['codex'], ['using'], 'project', cwd, home);
107
+ * ```
76
108
  */
77
- export function resolveTargets(providers, layers, scope, cwd = process.cwd(), home = homedir()) {
109
+ export const resolveTargets = (providers, layers, scope, cwd = process.cwd(), home = homedir()) => {
78
110
  const targets = [];
79
111
  for (const provider of providers) {
80
112
  const effectiveScope = supportsScope(provider, scope) ? scope : 'project';
@@ -90,4 +122,4 @@ export function resolveTargets(providers, layers, scope, cwd = process.cwd(), ho
90
122
  }
91
123
  }
92
124
  return targets;
93
- }
125
+ };