Skip to content

Use OpenAPI examples in generated snippets#143

Merged
KayleeWilliams merged 1 commit into
mainfrom
KayleeWilliams/openapi-example-data
Jul 7, 2026
Merged

Use OpenAPI examples in generated snippets#143
KayleeWilliams merged 1 commit into
mainfrom
KayleeWilliams/openapi-example-data

Conversation

@KayleeWilliams

Copy link
Copy Markdown
Collaborator

Summary

  • Use named OpenAPI request body examples, preferring examples.default, when generating cURL and JavaScript snippets.
  • Stop rendering request body examples as standalone blocks before code samples in markdown, TanStack, and Fumadocs OpenAPI renderers.
  • Add a patch changeset and update OpenAPI reference docs plus generated path hashes.

Why

Request body examples were shown once as Example: default and then generated snippets could still use synthesized placeholder payloads. That made the API reference repetitive and sometimes inconsistent. The request payload now appears where users copy it: in the generated snippets.

Validation

  • bun test packages/leadtype/src/openapi/openapi.test.ts
  • bun x ultracite check .changeset/tidy-openapi-examples.md apps/fumadocs-example/lib/mdx-components.tsx apps/tanstack/src/components/docs-mdx/api.tsx docs/paths.lock.json docs/reference/openapi.mdx packages/leadtype/src/markdown/plugins/openapi.ts packages/leadtype/src/openapi/index.ts packages/leadtype/src/openapi/openapi.test.ts

Note: the local pre-commit full-suite hook was not used for the final commit because leadtype CLI > runs lint against this repo's docs fails in this checkout with existing docs snippet type-resolution errors for Node/React/leadtype types outside this patch.

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Request body examples are now embedded in generated cURL and fetch snippets, using provided OpenAPI example data (including default when available).
    • Request/response documentation was updated to better describe how examples are presented alongside code samples.
  • Bug Fixes
    • Request body examples are no longer shown redundantly.
    • Named examples are preferred over schema placeholder values; “external-only” examples are ignored for snippet generation.
  • Tests
    • Added coverage to verify correct example selection and omission behavior in generated snippets.

Walkthrough

Request body example generation now prefers named OpenAPI examples, with request-body rendering updated to avoid repeating standalone examples. Documentation, tests, and related metadata were adjusted to match the new output.

Changes

Named OpenAPI example selection and request-body rendering

Layer / File(s) Summary
Core example selection
packages/leadtype/src/openapi/index.ts, packages/leadtype/src/openapi/openapi.test.ts
Adds preferred named-example selection for request-body sampling, skips external-only examples, and verifies generated snippets use example values instead of schema placeholders.
Markdown request-body example suppression
packages/leadtype/src/markdown/plugins/openapi.ts
renderMediaType now accepts options to omit a named example and suppress the single example for request-body markdown output.
MDX request-body example suppression
apps/fumadocs-example/lib/mdx-components.tsx, apps/tanstack/src/components/docs-mdx/api.tsx
MediaType and ApiRequestBody now suppress standalone request-body examples while still handling named examples.
Docs and metadata
docs/reference/openapi.mdx, docs/paths.lock.json, .changeset/tidy-openapi-examples.md
Updates the OpenAPI docs text, path hashes, and changeset entry to reflect the request-body example behavior.

Estimated code review effort: 2 (Simple) | ~12 minutes

Possibly related PRs

  • inthhq/leadtype#123: Adjusts the same OpenAPI-to-markdown and MDX rendering path for request-body examples and sample generation.

Poem

A bunny found examples tucked in place,
Named ones hopped forward with steady grace.
No duplicate nibble, no extra chew,
Just snippets and samples, crisp and new.
Thump-thump, the docs now flow just right 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: using OpenAPI examples in generated snippets.
Description check ✅ Passed The description accurately matches the changeset and explains the snippet, docs, and renderer updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch KayleeWilliams/openapi-example-data

Comment @coderabbitai help to get the list of available commands.

@KayleeWilliams KayleeWilliams changed the title [codex] Use OpenAPI examples in generated snippets ] Use OpenAPI examples in generated snippets Jul 7, 2026
@KayleeWilliams KayleeWilliams changed the title ] Use OpenAPI examples in generated snippets Use OpenAPI examples in generated snippets Jul 7, 2026
@KayleeWilliams KayleeWilliams marked this pull request as ready for review July 7, 2026 19:39

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — folds OpenAPI request-body examples into the generated cURL/fetch snippets instead of also rendering them as a standalone block before the code samples.

  • Prefer named examples in snippets — new preferredMediaExample in packages/leadtype/src/openapi/index.ts picks examples.default, else the first examples entry, else example; sampleRequestBody now uses it. Safe because normalizeExamplesMap already unwraps each Example object's .value and hasNamedExamples guarantees a non-empty map.
  • Suppress standalone request-body examples — an includeExamples flag is threaded symmetrically through renderMediaType (markdown/plugins/openapi.ts) and the MediaType components in apps/fumadocs-example/lib/mdx-components.tsx and apps/tanstack/src/components/docs-mdx/api.tsx; it defaults to true so response examples are unchanged, and request bodies pass false.
  • Docs + lock refreshdocs/reference/openapi.mdx prose and docs/paths.lock.json hashes updated to match.
  • Test coverageopenapi.test.ts asserts the named example lands in both cURL and fetch snippets and that the standalone Example: default block is gone.

ℹ️ Request bodies with multiple named examples now show only one

Previously every named request-body example rendered as its own standalone block; now the standalone blocks are suppressed and only the preferred (default, or first) example flows into the snippet. Specs that document several alternative request payloads will lose the non-preferred ones from the output entirely.

This is consistent with the PR's "tidy" intent and is not a bug — flagging only so the drop of alternative examples is a deliberate, known tradeoff rather than an accident.

Technical details
# Request bodies with multiple named examples now show only one

## Affected sites
- `packages/leadtype/src/openapi/index.ts:1168``preferredMediaExample` returns a single value (default / first entry).
- `packages/leadtype/src/markdown/plugins/openapi.ts:249` and the `MediaType` request-body call sites in `apps/fumadocs-example/lib/mdx-components.tsx` / `apps/tanstack/src/components/docs-mdx/api.tsx` — pass `includeExamples: false`, so the remaining named examples are no longer rendered anywhere.

## Required outcome
- No change required if losing non-preferred request examples is acceptable.

## Open questions for the human
- Do any specs in scope ship more than one named request-body example? If so, is dropping the alternatives from the reference intended, or should multiple examples still surface (e.g. as tabs or a collapsed block)?

Pullfrog  | View workflow run | Using Claude Opus𝕏

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 51b05e40f5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/leadtype/src/openapi/index.ts Outdated
Comment on lines +1170 to +1173
if (Object.hasOwn(media.examples, "default")) {
return media.examples.default;
}
return Object.values(media.examples)[0];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Don't use external-only Example objects as bodies

When a request body's examples.default is an OpenAPI Example Object that only has externalValue/metadata and no inline value, normalizeExamplesMap leaves that object in media.examples; this new return then makes generated cURL/fetch snippets post the metadata object itself instead of falling back to the schema/example payload. Guard named examples to only use actual inline values, or fall back when the selected example is external-only.

Useful? React with 👍 / 👎.

Comment on lines +248 to +249
for (const media of body.content) {
nodes.push(...renderMediaType(media));
nodes.push(...renderMediaType(media, { includeExamples: false }));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep non-selected request examples visible

When a request body defines multiple named examples, this suppresses the entire request-section example list, but the generated snippets only include one preferred example, so the remaining named examples disappear from the flattened markdown output. Keep the non-selected examples rendered somewhere, or only suppress the single example duplicated by the generated snippets.

Useful? React with 👍 / 👎.

@KayleeWilliams KayleeWilliams force-pushed the KayleeWilliams/openapi-example-data branch from 51b05e4 to 647c882 Compare July 7, 2026 19:55

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
apps/tanstack/src/components/docs-mdx/api.tsx (1)

136-165: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Same empty-examples fallthrough issue as apps/fumadocs-example/lib/mdx-components.tsx.

media.examples || includeSingleExample treats an empty examples: {} as truthy, so MediaTypeExamples can still fall back to rendering media.example even when includeSingleExample={false} (used by ApiRequestBody). Same fix as suggested for the fumadocs component: check Object.keys(media.examples ?? {}).length > 0 instead of relying on object truthiness.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/tanstack/src/components/docs-mdx/api.tsx` around lines 136 - 165, The
MediaType component still uses truthiness for media.examples, so an empty
examples object can incorrectly trigger MediaTypeExamples and fall back to
media.example even when includeSingleExample is false. Update the conditional in
MediaType to explicitly check whether media.examples has any keys, using the
same pattern as the fumadocs component, so ApiRequestBody does not render a
single example for empty examples.
apps/fumadocs-example/lib/mdx-components.tsx (1)

354-383: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Empty examples: {} can leak the single example even when includeSingleExample is false.

media.examples || includeSingleExample is truthy whenever media.examples is any object, including an empty one ({}). In that edge case MediaTypeExamples still renders, and since namedExamples.length is 0, it falls through to rendering media.example — defeating includeSingleExample={false} used by ApiRequestBody to avoid duplicating the request-body example that's now shown in the code sample.

🐛 Proposed fix
-      {media.examples || includeSingleExample ? (
+      {(media.examples && Object.keys(media.examples).length > 0) ||
+      includeSingleExample ? (
         <MediaTypeExamples
           media={media}
           omittedExampleName={omittedExampleName}
         />
       ) : null}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/fumadocs-example/lib/mdx-components.tsx` around lines 354 - 383, The
MediaType conditional currently treats any object in media.examples as truthy,
so an empty examples map still renders MediaTypeExamples and leaks media.example
even when includeSingleExample is false. Update the render guard in MediaType to
only show examples when there is at least one named example or
includeSingleExample is true, and ensure MediaTypeExamples is only reached when
it should actually display a single example; this will preserve the
ApiRequestBody behavior that suppresses the duplicate request-body example.
packages/leadtype/src/openapi/index.ts (1)

1193-1206: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated example-selection logic across 4 files.

isExternalOnlyExampleObject/preferredNamedExampleName-style logic is re-implemented nearly verbatim here, in packages/leadtype/src/markdown/plugins/openapi.ts, apps/fumadocs-example/lib/mdx-components.tsx, and apps/tanstack/src/components/docs-mdx/api.tsx. Any future fix (including the potential wrapping bug above) needs to be applied in 4 places. Consider exporting the shared helpers from this module (or a small shared utils file) and importing them in the other three consumers, since ApiMediaType is already aliased from OpenApiMediaType.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/leadtype/src/openapi/index.ts` around lines 1193 - 1206, The
example-selection logic in sampleRequestBody and its related helper flow is
duplicated across multiple consumers, so update this module to expose the shared
media-example helpers (including preferredMediaExample and the
isExternalOnlyExampleObject/preferredNamedExampleName behavior) from a common
place and have the other OpenAPI renderers import them instead of reimplementing
the same selection logic. Keep the behavior centralized around
OpenApiOperation/OpenApiMediaType so
packages/leadtype/src/markdown/plugins/openapi.ts,
apps/fumadocs-example/lib/mdx-components.tsx, and
apps/tanstack/src/components/docs-mdx/api.tsx all use the same implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/leadtype/src/openapi/openapi.test.ts`:
- Around line 676-742: The test in openapi.test.ts for generated request body
examples is too permissive and can miss a nested example wrapper regression.
Update the assertions around generateFixturePages, convertMdxToMarkdown, and the
extracted cURL/JavaScript snippets to parse the request body JSON and verify its
exact shape, or explicitly assert that no top-level "value" wrapper is present.
Use the existing sample lookup logic for the cURL and JavaScript codeSamples to
locate the payload before asserting on the unwrapped example contents.

---

Outside diff comments:
In `@apps/fumadocs-example/lib/mdx-components.tsx`:
- Around line 354-383: The MediaType conditional currently treats any object in
media.examples as truthy, so an empty examples map still renders
MediaTypeExamples and leaks media.example even when includeSingleExample is
false. Update the render guard in MediaType to only show examples when there is
at least one named example or includeSingleExample is true, and ensure
MediaTypeExamples is only reached when it should actually display a single
example; this will preserve the ApiRequestBody behavior that suppresses the
duplicate request-body example.

In `@apps/tanstack/src/components/docs-mdx/api.tsx`:
- Around line 136-165: The MediaType component still uses truthiness for
media.examples, so an empty examples object can incorrectly trigger
MediaTypeExamples and fall back to media.example even when includeSingleExample
is false. Update the conditional in MediaType to explicitly check whether
media.examples has any keys, using the same pattern as the fumadocs component,
so ApiRequestBody does not render a single example for empty examples.

In `@packages/leadtype/src/openapi/index.ts`:
- Around line 1193-1206: The example-selection logic in sampleRequestBody and
its related helper flow is duplicated across multiple consumers, so update this
module to expose the shared media-example helpers (including
preferredMediaExample and the
isExternalOnlyExampleObject/preferredNamedExampleName behavior) from a common
place and have the other OpenAPI renderers import them instead of reimplementing
the same selection logic. Keep the behavior centralized around
OpenApiOperation/OpenApiMediaType so
packages/leadtype/src/markdown/plugins/openapi.ts,
apps/fumadocs-example/lib/mdx-components.tsx, and
apps/tanstack/src/components/docs-mdx/api.tsx all use the same implementation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 12a02dc1-908c-4060-9582-eeea5f67997f

📥 Commits

Reviewing files that changed from the base of the PR and between 51b05e4 and 647c882.

📒 Files selected for processing (8)
  • .changeset/tidy-openapi-examples.md
  • apps/fumadocs-example/lib/mdx-components.tsx
  • apps/tanstack/src/components/docs-mdx/api.tsx
  • docs/paths.lock.json
  • docs/reference/openapi.mdx
  • packages/leadtype/src/markdown/plugins/openapi.ts
  • packages/leadtype/src/openapi/index.ts
  • packages/leadtype/src/openapi/openapi.test.ts
📜 Review details
⚠️ CI failures not shown inline (2)

GitHub Actions: CI / 0_Validate & test.txt: Use OpenAPI examples in generated snippets

Conclusion: failure

View job details

Current runner version: '2.335.1'
 ##[group]Runner Image Provisioner
 Hosted Compute Agent
 Version: 20260624.560
 Commit: 925d229a51159bc391ae97e54a2dd1fe20af789d
 Build Date:
 Worker ID: {73c54a00-2beb-4a19-8e35-f036b72343d3}
 Azure Region: northcentralus
 ##[endgroup]
 ##[group]Operating System
 Ubuntu
 24.04.4
 LTS
 ##[endgroup]
 ##[group]Runner Image
 Image: ubuntu-24.04
 Version: 20260628.225.1
 Included Software: https://github.com/actions/runner-images/blob/ubuntu24/20260628.225/images/ubuntu/Ubuntu2404-Readme.md
 Image Release: https://github.com/actions/runner-images/releases/tag/ubuntu24%2F20260628.225
 ##[endgroup]
 ##[group]GITHUB_TOKEN Permissions
 Contents: read
 Metadata: read
 ##[endgroup]
 Secret source: Actions
 Prepare workflow directory
 Prepare all required actions
 Getting action download info
 Download action repository 'actions/checkout@v4' (SHA:34e114876b0b11c390a56381ad16ebd13914f8d5)
 Download action repository 'oven-sh/setup-bun@v2' (SHA:0c5077e51419868618aeaa5fe8019c62421857d6)
 Complete job name: Validate & test
 Node 20 is being deprecated. This workflow is running with Node 24 by default. If you need to temporarily use Node 20, you can set the ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true environment variable. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
 ##[group]Run actions/checkout@v4
 with:
   repository: inthhq/leadtype
   ***REDACTED***
   ssh-strict: true
   ssh-user: git
   persist-credentials: true
   clean: true
   sparse-checkout-cone-mode: true
   fetch-depth: 1
   fetch-tags: false
   show-progress: true
   lfs: false
   submodules: false
   set-safe-directory: true
 ##[endgroup]
 Syncing repository: inthhq/leadtype
 ##[group]Getting Git version info
 Working directory is '/home/runner/work/leadtype/leadtype'
 [command]/usr/bin/git version
 git version 2.54.0
 ##[endgroup]
 Temporarily overriding HOME='/home/runner/work/_temp/3fdaa38c-0bbd-471d-9e2...

GitHub Actions: CI / Validate & test: Use OpenAPI examples in generated snippets

Conclusion: failure

View job details

##[group]Run bun run --filter leadtype test
 �[36;1mbun run --filter leadtype test�[0m
 shell: /usr/bin/bash -e {0}
 ##[endgroup]
 leadtype test:
 leadtype test: �[1m�[30m�[46m RUN �[49m�[39m�[22m �[36mv4.1.5 �[39m�[90m/home/runner/work/leadtype/leadtype/packages/leadtype�[39m
 leadtype test:
 leadtype test:  �[32m✓�[39m src/llm/llm.test.ts �[2m(�[22m�[2m86 tests�[22m�[2m)�[22m�[32m 269�[2mms�[22m�[39m
 leadtype test:  �[32m✓�[39m src/openapi/openapi.test.ts �[2m(�[22m�[2m34 tests�[22m�[2m)�[22m�[33m 411�[2mms�[22m�[39m
 leadtype test:  �[32m✓�[39m src/lint/lint.test.ts �[2m(�[22m�[2m45 tests�[22m�[2m)�[22m�[33m 1054�[2mms�[22m�[39m
 leadtype test:      �[33m�[2m✓�[22m�[39m warns on rendered components with no flattener but not on code-block examples �[33m 316�[2mms�[22m�[39m
 leadtype test: Converted 1 docs in 39 ms
 leadtype test: Converted 2 docs in 7 ms
 leadtype test: Converted 2 docs in 5 ms
 leadtype test: Pruned 1 orphaned .md file(s) from /tmp/leadtype-convert-PNSl2i/public
 leadtype test: Converted 2 docs in 9 ms
 leadtype test: Converted 1 docs in 1 ms
 leadtype test: Pruned 2 orphaned .md file(s) from /tmp/leadtype-convert-YAVyba/public
 leadtype test: Converted 1 docs in 5 ms
 leadtype test: Pruned 1 orphaned .md file(s) from /tmp/leadtype-convert-hi6Ssl/public
 leadtype test: Converted 1 docs in 2 ms
 leadtype test: Pruned 1 orphaned .md file(s) from /tmp/leadtype-convert-W33Dcj/public
 leadtype test: Converted 1 docs in 4 ms
 leadtype test: Error: failed to process /tmp/leadtype-convert-ScpIOU/docs/broken.mdx: 3:1: Unexpected character after `<`, expected a valid JSX tag (note: to create a link in MDX, use `[text](url)`) (mdx-jsx:unexpected-character)
 leadtype test: Converted 1 docs in 2 ms (1 failed)
 leadtype test: Warning: prune skipped: 1 file(s) failed to convert, so the expected output set is incomplete.
 leadtype test: Warning: prune skipped: no .mdx sources under /tmp/leadtype-convert-ZN2U8H/empty-docs — refusing to treat every output in /...
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use explicit types for function parameters and return values when they enhance clarity
Prefer unknown over any when the type is genuinely unknown
Use const assertions (as const) for immutable values and literal types
Leverage TypeScript's type narrowing instead of type assertions

Files:

  • packages/leadtype/src/openapi/openapi.test.ts
  • apps/tanstack/src/components/docs-mdx/api.tsx
  • packages/leadtype/src/markdown/plugins/openapi.ts
  • apps/fumadocs-example/lib/mdx-components.tsx
  • packages/leadtype/src/openapi/index.ts
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,ts,jsx,tsx}: Use meaningful variable names instead of magic numbers - extract constants with descriptive names
Use arrow functions for callbacks and short functions
Prefer for...of loops over .forEach() and indexed for loops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Use const by default, let only when reassignment is needed, never var
Always await promises in async functions - don't forget to use the return value
Use async/await syntax instead of promise chains for better readability
Handle errors appropriately in async code with try-catch blocks
Don't use async functions as Promise executors
Remove console.log, debugger, and alert statements from production code
Throw Error objects with descriptive messages, not strings or other values
Use try-catch blocks meaningfully - don't catch errors just to rethrow them
Prefer early returns over nested conditionals for error cases
Extract complex conditions into well-named boolean variables
Use early returns to reduce nesting
Prefer simple conditionals over nested ternary operators
Don't use eval() or assign directly to document.cookie
Avoid spread syntax in accumulators within loops
Use top-level regex literals instead of creating them in loops
Prefer specific imports over namespace imports
Use descriptive names for functions, variables, and types for meaningful naming
Add comments for complex logic, but prefer self-documenting code

Files:

  • packages/leadtype/src/openapi/openapi.test.ts
  • apps/tanstack/src/components/docs-mdx/api.tsx
  • packages/leadtype/src/markdown/plugins/openapi.ts
  • apps/fumadocs-example/lib/mdx-components.tsx
  • packages/leadtype/src/openapi/index.ts
**/*.{test,spec}.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{test,spec}.{js,ts,jsx,tsx}: Write assertions inside it() or test() blocks
Avoid done callbacks in async tests - use async/await instead
Don't use .only or .skip in committed code
Keep test suites reasonably flat - avoid excessive describe nesting

Files:

  • packages/leadtype/src/openapi/openapi.test.ts
**/*.{jsx,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{jsx,tsx}: Use function components over class components in React
Call hooks at the top level only, never conditionally
Specify all dependencies in hook dependency arrays correctly
Use the key prop for elements in iterables (prefer unique IDs over array indices)
Nest children between opening and closing tags instead of passing as props
Don't define components inside other components
Avoid dangerouslySetInnerHTML unless absolutely necessary
Use proper image components (e.g., Next.js <Image>) over <img> tags
Use Next.js <Image> component for images
Use next/head or App Router metadata API for head elements in Next.js
Use Server Components for async data fetching instead of async Client Components in Next.js
Use ref as a prop instead of React.forwardRef in React 19+

Files:

  • apps/tanstack/src/components/docs-mdx/api.tsx
  • apps/fumadocs-example/lib/mdx-components.tsx
**/*.{jsx,tsx,html}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{jsx,tsx,html}: Use semantic HTML and ARIA attributes for accessibility: provide meaningful alt text for images, use proper heading hierarchy, add labels for form inputs, include keyboard event handlers alongside mouse events, use semantic elements instead of divs with roles
Add rel="noopener" when using target="_blank" on links

Files:

  • apps/tanstack/src/components/docs-mdx/api.tsx
  • apps/fumadocs-example/lib/mdx-components.tsx
**/index.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Avoid barrel files (index files that re-export everything)

Files:

  • packages/leadtype/src/openapi/index.ts
🧠 Learnings (1)
📚 Learning: 2026-06-09T18:30:08.038Z
Learnt from: KayleeWilliams
Repo: inthhq/leadtype PR: 97
File: .changeset/search-prototype-safety-and-scaling.md:5-5
Timestamp: 2026-06-09T18:30:08.038Z
Learning: In this repo, `.changeset/*.md` files must not start the body with an H1/first-line heading (`#`) immediately after the YAML frontmatter. The changesets tool inlines the body as bullet entries into `CHANGELOG.md` during release, and a leading `#` heading would break the generated changelog format. As a result, MD041 (`first-line-heading`) warnings for files under `.changeset/` are expected false positives and should be ignored.

Applied to files:

  • .changeset/tidy-openapi-examples.md
🪛 ast-grep (0.44.1)
packages/leadtype/src/openapi/index.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { execFile } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

🪛 markdownlint-cli2 (0.22.1)
.changeset/tidy-openapi-examples.md

[warning] 5-5: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

🔇 Additional comments (13)
packages/leadtype/src/markdown/plugins/openapi.ts (3)

80-111: 📐 Maintainability & Code Quality | ⚡ Quick win

Duplicate of the helpers in packages/leadtype/src/openapi/index.ts.

isRecord, isExternalOnlyExampleObject, and the "preferred example" selection logic mirror packages/leadtype/src/openapi/index.ts almost exactly. See the duplication comment on that file; consolidating would reduce the maintenance surface for this logic.


128-142: LGTM!


267-290: LGTM!

apps/fumadocs-example/lib/mdx-components.tsx (2)

302-352: 📐 Maintainability & Code Quality | ⚡ Quick win

Duplicate of the helper logic used elsewhere.

Same isRecord/isExternalOnlyExampleObject/preferredNamedExampleName implementation as in packages/leadtype/src/openapi/index.ts and packages/leadtype/src/markdown/plugins/openapi.ts and apps/tanstack/src/components/docs-mdx/api.tsx. Worth consolidating into one shared exported utility.


394-399: LGTM!

apps/tanstack/src/components/docs-mdx/api.tsx (2)

84-134: 📐 Maintainability & Code Quality | ⚡ Quick win

Duplicate of the helper logic used elsewhere.

Identical isRecord/isExternalOnlyExampleObject/preferredNamedExampleName implementation as in apps/fumadocs-example/lib/mdx-components.tsx, packages/leadtype/src/markdown/plugins/openapi.ts, and packages/leadtype/src/openapi/index.ts. Recommend consolidating into a single shared utility exported from packages/leadtype.


289-294: LGTM!

.changeset/tidy-openapi-examples.md (1)

1-6: Expected MD041 false positive.

The markdownlint MD041 warning about a missing first-line heading is expected for .changeset/*.md files in this repo, since the changesets tool inlines the body as bullet entries into CHANGELOG.md and a leading # would break the format. Based on learnings, this warning should be ignored.

Source: Learnings

packages/leadtype/src/openapi/index.ts (2)

1185-1191: LGTM!


1168-1183: 🗄️ Data Integrity & Integration

No bug here: media.examples is already unwrapped. normalizeExamplesMap() converts each OpenAPI Example Object to its .value, so preferredMediaExample() returns the payload directly, not a nested { value: ... } object.

			> Likely an incorrect or invalid review comment.
packages/leadtype/src/openapi/openapi.test.ts (1)

744-780: LGTM!

docs/reference/openapi.mdx (1)

102-108: LGTM!

docs/paths.lock.json (1)

158-158: LGTM!

Also applies to: 190-190

Comment on lines +676 to +742
it("uses named request body examples in generated snippets", async () => {
const spec = `
openapi: 3.1.0
info: { title: Examples, version: 1.0.0 }
servers:
- url: https://api.example.com
paths:
/sites:
post:
operationId: createSite
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [organizationId, name]
properties:
organizationId:
type: string
name:
type: string
region:
type: string
consent:
type: object
properties:
branding:
type: string
examples:
default:
value:
organizationId: org_123
name: Website
region: us-east-1
consent:
branding: inth
enterprise:
value:
organizationId: org_456
name: Enterprise
region: eu-west-1
consent:
branding: custom
responses: { "201": { description: created } }
`;
const { result } = await generateFixturePages(spec);
const samples = result.pages[0]?.operation.codeSamples ?? [];
const curl = samples.find((sample) => sample.label === "cURL")?.code ?? "";
const fetch =
samples.find((sample) => sample.label === "JavaScript")?.code ?? "";

expect(curl).toContain('"organizationId": "org_123"');
expect(curl).toContain('"branding": "inth"');
expect(curl).not.toContain('"organizationId": "string"');
expect(fetch).toContain('"organizationId": "org_123"');
expect(fetch).toContain('"branding": "inth"');

const converted = await convertMdxToMarkdown(
result.pages[0]?.filePath ?? "",
defaultMarkdownTransforms
);
expect(converted.markdown).not.toContain("Example: default");
expect(converted.markdown).toContain("Example: enterprise");
expect(converted.markdown).toContain('"organizationId": "org_456"');
expect(converted.markdown).toContain('"organizationId": "org_123"');
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Assertions are too loose to catch an example-wrapping regression.

toContain('"organizationId": "org_123"') would still pass even if the generated body were incorrectly nested (e.g. {"value": {"organizationId": "org_123", ...}}) rather than flat, since it's only a substring check. Consider parsing the extracted JSON payload from the snippet and asserting on its exact shape (e.g. expect(JSON.parse(extractedBody)).toEqual({ organizationId: "org_123", ... })), or at least assert the absence of a wrapping "value": key, to guard against the example object being used verbatim instead of its unwrapped payload.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/leadtype/src/openapi/openapi.test.ts` around lines 676 - 742, The
test in openapi.test.ts for generated request body examples is too permissive
and can miss a nested example wrapper regression. Update the assertions around
generateFixturePages, convertMdxToMarkdown, and the extracted cURL/JavaScript
snippets to parse the request body JSON and verify its exact shape, or
explicitly assert that no top-level "value" wrapper is present. Use the existing
sample lookup logic for the cURL and JavaScript codeSamples to locate the
payload before asserting on the unwrapped example contents.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — the branch was rebased into a single commit that reworks how request-body examples are rendered and adds handling for external-only OpenAPI Example Objects, since the prior pullfrog review at 51b05e4.

  • Preserve non-preferred named examples — request bodies previously suppressed every standalone example (includeExamples: false); now only the example that flows into the snippet is omitted (omitExampleName / omittedExampleName), and the remaining named examples still render as standalone blocks. This resolves the prior review's note that alternative named examples were being dropped.
  • Skip external-only examples — a shared isExternalOnlyExampleObject helper (added to packages/leadtype/src/openapi/index.ts, markdown/plugins/openapi.ts, and both MediaType renderers) detects Example Objects with externalValue but no inline value; preferredMediaExample skips them and sampleRequestBody falls back to a schema-synthesized payload.
  • Renamed renderer propincludeExamplesincludeSingleExample, with a new preferredNamedExampleName in each renderer mirroring preferredMediaExample's selection order so the omitted standalone example matches the one used in the snippet.
  • Test coverage — the uses named request body examples test now asserts a second enterprise example still surfaces standalone, and a new ignores external-only request body examples test asserts external-only payloads are excluded from both cURL and fetch snippets. Full 34-test openapi suite passes.

ℹ️ External-only examples still render as standalone JSON in request bodies

The new isExternalOnlyExampleObject guard keeps external-only Example Objects out of the generated snippet, but the standalone renderers don't apply the same filter. When a request body has a non-preferred named example that is external-only, MediaTypeExamples (fumadocs/tanstack) and renderMediaType (markdown) still emit it as an Example: <name> block whose JSON body is the raw { "summary": ..., "externalValue": "https://..." } Example Object rather than an actual payload.

This is mergeable as-is — external-only request examples are rare, and surfacing the reference isn't strictly wrong — but the snippet-vs-standalone asymmetry may be unintended given the PR explicitly added the external-only guard for the snippet path.

Technical details
# External-only examples still render as standalone JSON in request bodies

## Affected sites
- `apps/fumadocs-example/lib/mdx-components.tsx``MediaTypeExamples` maps over `namedExamples` filtering only `omittedExampleName`; an external-only entry that isn't the preferred one is rendered via `<JsonExample value={value} />` where `value` is the intact `{ summary, externalValue }` object.
- `apps/tanstack/src/components/docs-mdx/api.tsx` — same `MediaTypeExamples` shape.
- `packages/leadtype/src/markdown/plugins/openapi.ts``renderMediaType` iterates `media.examples` skipping only `omitExampleName`; external-only entries reach `renderJsonExample(value)`.

## Required outcome
- Decide whether external-only examples should appear as standalone blocks at all in the request-body context; if not, skip entries where `isExternalOnlyExampleObject(value)` in the same three sites (and/or render the external URL as a link rather than a JSON dump).

## Open questions for the human
- Is dumping the raw `externalValue` Example Object as JSON intended, or should external-only examples be linked / omitted from the standalone render the way they're already excluded from the snippet?

Pullfrog  | View workflow run | Using Claude Opus𝕏

@KayleeWilliams KayleeWilliams merged commit fd79078 into main Jul 7, 2026
4 checks passed
@KayleeWilliams KayleeWilliams deleted the KayleeWilliams/openapi-example-data branch July 7, 2026 20:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant