Skip to content

Codegen: Support union types as scala 3 union types #1926

@oyvindberg

Description

@oyvindberg

With namespacing gone after #1925, we're quite close to being able to output union types as union types.

The remaining issue is basically this:

The problem is that Scala 3 doesn't generate Mirror for union types, so we can't use typeclass derivation for it: scala/scala3#15279

That's true. But, and I'm on very thin ice here, I think we can write a macro which pattern matches on the union type, picks out all the members and summonAlls Schemas for them.

Then we need to generate some code like this:

  type SearchResult = Human | Droid | Starship

  given Schema[Any, SearchResult] = Schema.typeUnion[SearchResult]

  // which would expand to something like this
  given Schema[Any, SearchResult] with {
    val _1: Schema[Any, Human] = summon[Schema[Any, Human]]
    val _2: Schema[Any, Droid] = summon[Schema[Any, Droid]]
    val _3: Schema[Any, Starship] = summon[Schema[Any, Starship]]
    val subTypes = List(_1, _2, _3)

    def resolve(value: SearchResult): caliban.schema.Step[Any] =
      value match {
        case x: Human => _1.resolve(x)
        case x: Droid => _2.resolve(x)
        case x: Starship => _3.resolve(x)
      }

    def toType(isInput: Boolean, isSubscription: Boolean): caliban.introspection.adt.__Type =
      caliban.schema.Types.makeUnion(Some("SearchResult"), None, subTypes.map(_.toType_(isInput, isSubscription)))
  }

Originally posted by @oyvindberg in #1925 (comment)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestserverIssue related to caliban servertoolsIssue related to Caliban tools like code generation or schema comparison

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions