TMDb Swift Package

repository·main·Indexed 41 days ago

https://github.com/adamayoung/tmdb

A comprehensive Swift package for interacting with The Movie Database (TMDb) API. It supports movies, TV shows, people, and more, featuring modern Swift concurrency, a dedicated TMDbTesting target for mocks and stubs, and TMDbIntelligence for on-device natural language search via Apple Intelligence. Version 19.0.0 introduces structured TMDbError context and the use of the Duration type for runtimes.

Tokens
82K
Snippets
205
Records
446
Agent score
51%

What's inside TMDb

  1. Understand the Engineering Knowledge Base structure

    main

    The Engineering Knowledge Base contains durable, project-specific reference material (the 'why', 'what', and 'gotchas') for the TMDb Swift package. It is distinct from imperative 'how-to' instructions found in CLAUDE.md or .claude/docs/.

    Knowledge File Mapping

    FileContents
    decisions/ADRs (Architecture Decision Records). One per decision, numbered and dated. Used for non-obvious design choices and their rationale.
    gotchas.mdImplementation quirks, tooling traps, and issues that required external research to resolve.
    tmdb-api-notes.mdObserved behaviors of the live TMDb API (e.g., nullable/absent fields, undocumented quirks, response-shape surprises).
    delivery-retros.mdShort retrospectives per feature delivered via /deliver. Covers what worked, friction, deviations, and improvements.
    skill-improvement-log.mdDecisions on skill-improvement proposals (applied, deferred, or rejected) to prevent re-proposing settled calls.
    next-major.mdBreaking-change backlog. Approved-in-principle changes waiting for a major version bump.
  2. How-To Guides Overview

    main

    The library provides several high-level guides to help you implement common features. Key functional areas include:

    • Content Discovery: Fetching movie/TV details, discovering new content, searching, and working with trending items.
    • Data Management: Using auto-pagination for large lists, generating image URLs, and managing user accounts.
    • Advanced Features: Authenticating with v4, handling errors, caching responses, and managing user lists.
  3. Maintain the `TMDbError.invalidRating` error case

    main

    The TMDbError.invalidRating error must remain a distinct, standalone error case and should not be merged into .badRequest.

    Rationale:

    • .invalidRating is an on-device argument-validation failure that occurs before a request is sent.
    • .badRequest is intended for server-side responses that include a TMD_ErrorContext payload.
    • Merging them would lose the ability for callers to distinguish between a local validation error (where the context is nil) and a rejection from the TMDb server.
  4. Prevent divergence when adding sibling components

    main

    To ensure new code conforms to existing patterns within a family (e.g., adding a new Service to an existing set of Services), follow these two steps:

    1. Prevention (during /implement-plan): In Step 1, when adding a sibling to an existing family, read the 1–2 nearest siblings first. Explicitly capture their shared conventions (such as validation logic, error handling, conformance sets, decoding strategies, or test suite tags) as items in your test list.
    2. Detection (during code review): Ensure new family members match their siblings. Divergence in architecture or testing dimensions (e.g., using .requests instead of .services tags) should be flagged during the review process.
  5. Handle skipped items in pageable results via `droppedItemCount`

    main

    When using tolerant containers, some items may be skipped if they contain an unmodelled media_type. To help with debugging or reconciliation, certain containers include a droppedItemCount property.

    Important Constraints:

    • The droppedItemCount is marked as package access. While it is available on the models, it is intended for internal package use and is not meant to be relied upon by external consumers for business logic.
    • The count is stored as a DroppedItemCount type where == is always true and hash(into:) writes nothing. This ensures that the presence of skipped items does not affect the Equatable or Hashable identity of the model. A decoded page will still equal its own encode-decode round trip, even if items were skipped.
  6. Beware of silent sequence termination in PagedAsyncSequence

    main

    When using a PagedAsyncSequence with a 'tolerant' decoding container (one that skips unmodelled rows instead of throwing), you may encounter silent sequence termination.

    The Problem: PagedAsyncSequence stops when it receives a page with an empty results array. However, if a page contains rows that are all unmodelled/skipped by your tolerant decoder, the resulting results array will be empty. The sequence will interpret this as the end of the data and stop, even if there are more valid pages following it.

    Risk: This manifests as a truncated sequence rather than a decoding error, making it difficult to debug.

  7. Override agent model tiers using call-site instructions

    main

    When calling an agent or skill, you can override the model tier defined in the agent's frontmatter.

    The Override Rule: An Agent-tool call-site model: override beats the agent definition's frontmatter pin. The frontmatter pin acts as a floor (the minimum quality), not a ceiling. This allows you to force a high-judgment model (like model: opus) for a specific task even if the agent is normally pinned to a cheaper tier (like Haiku).

  8. AuthenticatedSession persistence and Codable support

    main

    The AuthenticatedSession type does not conform to Codable. This is a deliberate design choice to avoid creating a permanent serialization contract for sensitive credentials (session.sessionID).

    If you need to persist an authenticated session (e.g., for a 'remembered login' feature), you are responsible for securely storing the individual components (accountID and session) yourself.

  9. Manage user accounts with AccountService

    main
    The AccountService provides an interface for interacting with a user's personal TMDb account data. It allows you to retrieve account details, manage authenticated sessions, and interact with user-specific collections such as favorites, watchlists, ratings, and custom lists. Most methods require either an authenticatedSession or a combination of an accountID and a session to authorize requests.
  10. Build discovery filters using DiscoverMovieFilter

    main

    The DiscoverService allows you to build complex queries using a fluent builder pattern. Methods return a new filter instance, allowing you to compose filters without mutating shared state. You can also control how multi-valued parameters (like genres) are joined using DiscoverFilterJoin (e.g., .or vs the default .and).

    // Match movies tagged with genre 28 OR genre 12
    let filter = DiscoverMovieFilter()
        .withGenres([28, 12], joinedBy: .or)
        .voteAverage(in: 7...10)
        .primaryReleaseYear(.on(2024))
    
    let movies = try await tmdbClient.discover.movies(
        filter: filter,
        sortedBy: .popularity(descending: true)
    )