Coder Social home page Coder Social logo

caliban-deriving's Introduction

Caliban Deriving

Full-featured, robust deriving for Caliban.

Development CI Badge Sonatype Releases Sonatype Snapshots javadoc Caliban Deriving

The Caliban Deriving library provides an advanced derive macro for the Caliban library that seamlessly integrates with the built-in schema derivation system and allows the library users to not only derive the schema for the user defined case classes and enums but also for calculated fields and functions with parameters.

Getting started

Start by adding caliban-deriving as a dependency to your project:

libraryDependencies += "dev.zio" %% "caliban-deriving" % "0.0.1"

Once the library is added, Caliban's default auto-derived schemas can be replaced one by one for each type by explicitly deriving its schema using the Caliban Deriving method:

case class Example(value: Int)
object Example {
    implicit lazy val exampleSchema: Schema[Any, Example] =
      deriveSchemaInstance[Any, Example]
}

Please read Caliban's official documentation about schemas to learn more about what a schema is and what features the core library provides.

It is important that it is possible to use a mix of Caliban's built-in schemas, auto-derived schemas and the ones provided by deriveSchemaInstance. Both derive methods are looking for implicit instances of Schema.

Features

Caliban Deriving's deriveSchemaInstance function can be applied on the following Scala data types:

  • case classes
  • sealed traits or Scala 3 enums
  • any trait

Common features

The following rules apply equally for case classes, sealed traits and traits.

  • public val fields and parameterless def methods are generated as GraphQL fields. Their Schema is found by an implicit search for the given type. This way it supports exactly the same cases as Caliban's built-in derive method, including fields of type ZIO, ZQuery and Future.
  • public methods with one or more parameters are generated as GraphQL functions. The Schema of the function arguments is found by an implicit search for their type.
  • protected and private fields/methods are excluded
  • public members annotated by @GQLExclude are also excluded
  • the following core Caliban annotations are supported: @GQLName, @GQLDescription, @GQLDeprecated and @GQLDirective

Case classes

From case classes a GraphQL type is generated. If it is used as an input (as a parameter for a function in another type), then an GraphQL input is generated which only contains the constructor parameters of the case class, not the other members.

Sealed traits

For sum types (sealed trait with a set of case class / case objects implementations) if the base trait contains any methods, it will become a GraphQL interface and each constuctor a type.

If the base trait has no members, but the constructors have parameters, it becomes a GraphQL union. Members of constructors are still handled the same way as mentioned above.

If all the constructors are case objects then it becomes a GraphQL enum.

Traits

If the derivation is invoked on a simple trait (not sealed) then it works as if it were a concrete parameterless case class. This means a GraphQL type is generated and a schema derived for an arbitrary trait can be used to serve any implementation of it.

Using with effects

When there are members of type ZIO or ZQuery, they can have an environment parameter (-R) that is not Any. Effects and queries without environment just work.

When working with effects requiring an environment the following rules apply:

  • You have to have the GenericSchema[R] trait in scope as described in the official documentation. This should be done by inheriting this trait in an object and putting all the additional derived implicits there.
  • The implicit resolution in this case will only be correct if you put all the implicit instances derived with Caliban Deriving's deriveSchemaInstance directly into the object extending GenericSchema.
  • Although the macro can calculate the union of all the required environments used in a type, it is not automatically using it for the result Schema. The reason is that you may want to derive schema for multiple data types, each using only a subset of the total environment passed to the GenericSchema. In this case the full environment cannot be calculated inside the derivation. For this reason, you must provide the full required environment, the same that is passed to the GenericSchema in scope, to the deriveSchemaInstance method in its first type parameter.

Mutations and subscriptions

Not supported yet.

Documentation

Learn more on the Caliban Deriving homepage!

Contributing

For the general guidelines, see ZIO contributor's guide.

Code of Conduct

See the Code of Conduct

Support

Come chat with us on Badge-Discord.

License

License

caliban-deriving's People

Contributors

argson67 avatar jdegoes avatar khajavi avatar renovate-bot avatar renovate[bot] avatar scala-steward avatar vigoo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

caliban-deriving's Issues

work with public methods parameters

Having toy type example

case class Book(name: String) {
    def timesName(n: Option[Int] = Some(42)) = name * n.get
}
object Book {
    implicit val bookSchema: Schema[Any, Book] = deriving.deriveSchemaInstance[Any, Book]
}

and 1 simple query returning default book I face some inconvenience moments.

  1. it works strangly with Option: calling timesName w/o n (which is valid)
query{
  book{
    name
    timesName
  }
}

leads to

{
  "data": null,
  "errors": [
    {
      "message": "java.util.NoSuchElementException: key not found: n"
    }
  ]
}

In addition it does not take default value into account
2) making n not optional, but just int leads generated schema to have parametr with !

To sum up: it would be nice to have input type/argument default value support and (ideally) treating fields with default values as optional during schema generating.
P.S. the same functionality in sangria is implemented with annotation, but unfortenutly it fails to make a field optional

Request for The Next Minor Release

I noticed that the latest version of the Caliban-deriving library is not available on the website. This means that users who rely on the website for documentation may not have access to the most up-to-date information.

We want to reflect the latest version of docs on the zio.dev website across all zio ecosystem libraries. In order to update the website with the latest documentation, we need a new library release.

Upgrade to ZIO 2.0

ZIO 2.0 is at Milestone 4, with an RC expected in the next few weeks.
https://github.com/zio/zio/releases/tag/v2.0.0-M4

The API is nearly stable at this point, so any early migration work against this version should pay off towards the official 2.0 release.

The progress is being tracked here:
zio/zio#5470

The Stream Encoding work in progress is the only area where the API might still change before the RC.

We are actively working on a ScalaFix rule that will cover the bulk of the simple API changes:
https://github.com/zio/zio/blob/series/2.x/scalafix/rules/src/main/scala/fix/Zio2Upgrade.scala
We highly recommend starting with that, and then working through any remaining compilation errors :)

To assist with the rest of the migration, we have created this guide:
https://zio.dev/howto/migrate/zio-2.x-migration-guide/

If you would like assistance with the migration from myself or other ZIO contributors, please let us know!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.