Skip to content

Extract inline response schemas into named component schemas#114

Open
LukasParke wants to merge 1 commit intomainfrom
normalize-inline-schemas
Open

Extract inline response schemas into named component schemas#114
LukasParke wants to merge 1 commit intomainfrom
normalize-inline-schemas

Conversation

@LukasParke
Copy link
Owner

@LukasParke LukasParke commented Mar 12, 2026

Summary

  • Extract 29 new named schemas from inline response definitions, eliminating duplication and ensuring Speakeasy SDKs generate proper named model classes instead of anonymous inline types
  • Fix MediaContainerWithDevice to reference the existing Device schema instead of redefining it inline
  • Convert 11 endpoint responses to use existing/new MediaContainerWith* wrapper schemas via $ref

Details

Phase 1 — Deduplicated schemas (highest value)

Schema Copies removed Notes
DVR 8 → 1 All 8 identical inline definitions across DVR endpoints
DecisionResult Extracted from DownloadQueueItem 9 decision properties
DownloadQueueItem 2 → 1 Contains $ref to DecisionResult
DownloadQueue 2 → 1 Queue status with enum
PlaybackHistoryMetadata 2 → 1 Reconciled 11-property subset to 16-property superset

Phase 2 — Single-use inline extractions (22 schemas)

Each of these was defined inline in a single endpoint response and is now a named schema:

Activity, TranscodeJob, ButlerTask, UltraBlurColors, EPGCountry, EPGLanguage, EPGRegion, MediaGrabber, DeviceChannel, Marker, TopUserAccount, Release, PlayQueueResponse, Bandwidth, AddedQueueItem, Level, Connection, ConnectionInfo, ConnectionInfoWrapper, Feature, ManagedHub

Phase 3 — Fixed existing schema references

  • MediaContainerWithDevice: Replaced 14-property inline Device definition with $ref: '#/components/schemas/Device' (byte-for-byte identical)
  • 7 Hub endpoints$ref: MediaContainerWithHubs
  • 1 Directory endpoint$ref: MediaContainerWithDirectory
  • New wrapper schemas: MediaContainerWithSorts, MediaContainerWithTags, MediaContainerWithMediaGrabOperation

What was NOT changed

  • Simple type aliases (Key, Thumb, Title, Type, BoolInt, AllowSync)
  • Metadata schema internal structure
  • Media/Part/Stream hierarchy
  • Endpoint-specific custom inline objects (e.g., firstCharacters, location, tags endpoints with unique property sets)
  • Player vs Device — fundamentally different concepts

Impact

  • Before: 45 schemas, ~62 endpoints with inline response schemas
  • After: 74 schemas, inline duplication eliminated
  • Net: −299 lines (960 removed, 661 added)
  • YAML validates successfully

Test plan

  • YAML validity: python3 -c "import yaml; yaml.safe_load(open('plex-api-spec.yaml'))"
  • All 29 new schemas present under components/schemas
  • No orphaned schemas (every schema referenced at least once)
  • Schema equivalence: resolved schemas match original inline definitions
  • Speakeasy SDK regeneration: verify named models (DVR, Activity, ButlerTask, etc.) appear as SDK classes
  • speakeasy lint openapi --schema plex-api-spec.yaml

🤖 Generated with Claude Code

Summary by CodeRabbit

  • API Updates
    • Introduced 20+ new public schema definitions for DVR management, Markers, Connection information, Bandwidth metrics, Playback History metadata, and EPG configuration data
    • Standardized API response structures across multiple endpoints for improved consistency and reliability
    • Reorganized schema definitions for cleaner documentation and enhanced developer integration

…hemas

Extract 29 new named schemas from inline definitions, eliminating
duplication and ensuring Speakeasy SDKs generate proper named model
classes instead of anonymous inline types.

Phase 1 - Deduplicated schemas:
- DVR (8 identical copies → 1 schema)
- DecisionResult + DownloadQueueItem (2 copies each)
- DownloadQueue (2 copies)
- PlaybackHistoryMetadata (2 divergent copies reconciled to 16-property superset)

Phase 2 - Single-use inline extractions:
- Activity, TranscodeJob, ButlerTask, UltraBlurColors
- EPGCountry, EPGLanguage, EPGRegion
- MediaGrabber, DeviceChannel, Marker, TopUserAccount
- Release, PlayQueueResponse, Bandwidth, AddedQueueItem, Level
- Connection, ConnectionInfo, ConnectionInfoWrapper
- Feature, ManagedHub

Phase 3 - Fixed existing schema references:
- MediaContainerWithDevice now uses $ref to Device schema
- 7 Hub endpoints → $ref MediaContainerWithHubs
- Directory/Sort/Tag/MediaGrabOperation endpoints → new wrapper schemas

Net result: -299 lines (960 removed, 661 added), 45 → 74 total schemas.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 12, 2026

📝 Walkthrough

Walkthrough

I trust this revision shall prove most gratifying, sir. The specification has undergone a most thorough modernisation, wherein numerous inline schema definitions have been supplanted with formal public component references throughout the document. One has introduced seven-and-twenty new public entity schemas whilst standardising their deployment across multiple endpoints, thereby extending the API's public surface with considerably greater consistency and propriety.

Changes

Cohort / File(s) Summary
Schema Refactoring and Expansion
plex-api-spec.yaml
Replaced inline schema definitions with public component references (DVR, DecisionResult, DownloadQueueItem, DownloadQueue, PlaybackHistoryMetadata, Activity, TranscodeJob, ButlerTask, UltraBlurColors, EPGCountry, EPGLanguage, EPGRegion, MediaGrabber, DeviceChannel, Marker, TopUserAccount, Release, PlayQueueResponse, Connection, ConnectionInfo, ConnectionInfoWrapper, Feature, ManagedHub, Bandwidth, AddedQueueItem, Level). Introduced new MediaContainer variants (MediaContainerWithMediaGrabOperation, MediaContainerWithSorts, MediaContainerWithTags). Standardised cross-endpoint usage of newly defined public entities, expanding API surface whilst improving type consistency.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

In spec files grand, with schemas neat,
One hundred schemas now complete—
Where chaos dwelt in lines inline,
Public components now align.
A butler's dream: all properly arranged!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and accurately describes the primary change: extracting inline schemas into named component schemas, which aligns precisely with the PR's main objective and file modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch normalize-inline-schemas

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plex-api-spec.yaml`:
- Around line 8024-8026: The response schema for the filters endpoint currently
uses MediaContainerWithDirectory which types each entry as Directory; update the
OpenAPI wrapper so the MediaContainer's Directory array maps to the existing
Filter schema instead of Directory (i.e. change the component reference under
MediaContainerWithDirectory's Directory items from Directory to Filter
/#/components/schemas/Filter) so generated models expose filterType, descKey and
other Filter fields; update any references in MediaContainerWithDirectory and
components/schemas to reflect Directory[] -> Filter[] for this endpoint.
- Around line 3085-3087: The response schema composing MediaContainer and
PlayQueueResponse has dropped the initial queue items; update the allOf
composition to also include the response Metadata array so clients receive the
queue contents returned by createPlayQueue. Specifically, modify the wrapper
that currently references MediaContainer and PlayQueueResponse to additionally
reference or define the Metadata array component (the same array used elsewhere
for item metadata) so the composed schema contains MediaContainer,
PlayQueueResponse, and the Metadata array.
🪄 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: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0480fe1a-f34f-4f63-8e21-8ecc6b671128

📥 Commits

Reviewing files that changed from the base of the PR and between 69cd459 and fb5ad44.

📒 Files selected for processing (1)
  • plex-api-spec.yaml

Comment on lines 3085 to +3087
allOf:
- $ref: '#/components/schemas/MediaContainer'
- properties:
playQueueID:
description: The ID of the play queue, which is used in subsequent requests.
type: integer
playQueueLastAddedItemID:
description: Defines where the "Up Next" region starts
type: string
playQueueSelectedItemID:
description: The queue item ID of the currently selected item.
type: integer
playQueueSelectedItemOffset:
description: The offset of the selected item in the play queue, from the beginning of the queue.
type: integer
playQueueSelectedMetadataItemID:
description: The metadata item ID of the currently selected item (matches `ratingKey` attribute in metadata item if the media provider is a library).
type: integer
playQueueShuffled:
description: Whether or not the queue is shuffled.
type: boolean
playQueueSourceURI:
description: The original URI used to create the play queue.
type: string
playQueueTotalCount:
description: The total number of items in the play queue.
type: integer
playQueueVersion:
description: The version of the play queue. It increments every time a change is made to the play queue to assist clients in knowing when to refresh.
type: integer
type: object
- $ref: '#/components/schemas/PlayQueueResponse'
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Pray restore the queue items in this response.

Line 3087 composes MediaContainer with PlayQueueResponse only, so the Metadata array promised by createPlayQueue is no longer part of the schema. Generated clients will expose the queue metadata but not the initial queue contents.

Suggested adjustment
-                properties:
-                  MediaContainer:
-                    allOf:
-                      - $ref: '#/components/schemas/MediaContainer'
-                      - $ref: '#/components/schemas/PlayQueueResponse'
-                type: object
+                $ref: '#/components/schemas/MediaContainerWithPlayQueue'

That wrapper should compose #/components/schemas/MediaContainer, #/components/schemas/PlayQueueResponse, and the response Metadata array.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plex-api-spec.yaml` around lines 3085 - 3087, The response schema composing
MediaContainer and PlayQueueResponse has dropped the initial queue items; update
the allOf composition to also include the response Metadata array so clients
receive the queue contents returned by createPlayQueue. Specifically, modify the
wrapper that currently references MediaContainer and PlayQueueResponse to
additionally reference or define the Metadata array component (the same array
used elsewhere for item metadata) so the composed schema contains
MediaContainer, PlayQueueResponse, and the Metadata array.

Comment on lines 8024 to +8026
application/json:
schema:
properties:
MediaContainer:
allOf:
- $ref: '#/components/schemas/MediaContainer'
- properties:
Directory:
items:
$ref: '#/components/schemas/Directory'
type: array
type: object
type: object
$ref: '#/components/schemas/MediaContainerWithDirectory'
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

This wrapper is too general for the filters endpoint.

Lines 8024-8026 now point at MediaContainerWithDirectory, which types each entry as a plain Directory. This route returns filter descriptors, and the spec already has a Filter schema for fields such as filterType and descKey; otherwise the generated models lose that typed surface.

Suggested adjustment
-              schema:
-                $ref: '#/components/schemas/MediaContainerWithDirectory'
+              schema:
+                $ref: '#/components/schemas/MediaContainerWithFilters'

That wrapper should map MediaContainer.Directory[] to #/components/schemas/Filter.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plex-api-spec.yaml` around lines 8024 - 8026, The response schema for the
filters endpoint currently uses MediaContainerWithDirectory which types each
entry as Directory; update the OpenAPI wrapper so the MediaContainer's Directory
array maps to the existing Filter schema instead of Directory (i.e. change the
component reference under MediaContainerWithDirectory's Directory items from
Directory to Filter /#/components/schemas/Filter) so generated models expose
filterType, descKey and other Filter fields; update any references in
MediaContainerWithDirectory and components/schemas to reflect Directory[] ->
Filter[] for this endpoint.

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