From b3fb6524a1f593b5519ebaee06d689036a674849 Mon Sep 17 00:00:00 2001 From: Pierre Ricadat Date: Tue, 24 Sep 2024 08:00:33 +0000 Subject: [PATCH] [ci skip] update docs --- docs/404.html | 6 ++-- docs/about/index.html | 4 +-- .../js/{24.3b70fa72.js => 24.751a4ded.js} | 2 +- .../js/{25.84e7c3a0.js => 25.a67f9e7a.js} | 2 +- .../js/{26.75721902.js => 26.a75153e4.js} | 2 +- .../js/{27.28800ed0.js => 27.93ecdab2.js} | 2 +- .../js/{29.8ad5262b.js => 29.e973475c.js} | 2 +- .../js/{31.1784d0cb.js => 31.33bf616d.js} | 2 +- .../js/{32.b1b1b9b3.js => 32.e98c24dd.js} | 2 +- .../js/{36.d71a9373.js => 36.16ab13ff.js} | 2 +- .../js/{37.27a657f8.js => 37.462d58e3.js} | 2 +- .../js/{38.8217efc7.js => 38.aa2dfc31.js} | 2 +- .../js/{39.0ecd4a9a.js => 39.7e53426c.js} | 2 +- .../js/{40.72c059af.js => 40.5a62ccfc.js} | 2 +- .../js/{app.7daa26fd.js => app.cd7b3176.js} | 4 +-- docs/docs/adapters.html | 6 ++-- docs/docs/client-codegen.html | 6 ++-- docs/docs/client.html | 10 +++---- docs/docs/examples.html | 4 +-- docs/docs/federation.html | 6 ++-- docs/docs/index.html | 28 +++++++++---------- docs/docs/interop.html | 4 +-- docs/docs/laminext.html | 6 ++-- docs/docs/middleware.html | 6 ++-- docs/docs/optimization.html | 4 +-- docs/docs/relay-connections.html | 4 +-- docs/docs/schema-comparison.html | 4 +-- docs/docs/schema-reporting.html | 4 +-- docs/docs/schema.html | 4 +-- docs/docs/server-codegen.html | 6 ++-- docs/docs/stitching.html | 6 ++-- docs/docs/tools.html | 6 ++-- docs/faq/index.html | 4 +-- docs/index.html | 4 +-- docs/resources/index.html | 4 +-- 35 files changed, 82 insertions(+), 82 deletions(-) rename docs/assets/js/{24.3b70fa72.js => 24.751a4ded.js} (96%) rename docs/assets/js/{25.84e7c3a0.js => 25.a67f9e7a.js} (99%) rename docs/assets/js/{26.75721902.js => 26.a75153e4.js} (99%) rename docs/assets/js/{27.28800ed0.js => 27.93ecdab2.js} (99%) rename docs/assets/js/{29.8ad5262b.js => 29.e973475c.js} (99%) rename docs/assets/js/{31.1784d0cb.js => 31.33bf616d.js} (99%) rename docs/assets/js/{32.b1b1b9b3.js => 32.e98c24dd.js} (99%) rename docs/assets/js/{36.d71a9373.js => 36.16ab13ff.js} (99%) rename docs/assets/js/{37.27a657f8.js => 37.462d58e3.js} (99%) rename docs/assets/js/{38.8217efc7.js => 38.aa2dfc31.js} (99%) rename docs/assets/js/{39.0ecd4a9a.js => 39.7e53426c.js} (99%) rename docs/assets/js/{40.72c059af.js => 40.5a62ccfc.js} (96%) rename docs/assets/js/{app.7daa26fd.js => app.cd7b3176.js} (97%) diff --git a/docs/404.html b/docs/404.html index b4daa11be9..cc541cfdfc 100644 --- a/docs/404.html +++ b/docs/404.html @@ -8,13 +8,13 @@ - + -

404

Looks like we've got some broken links.
+ - + diff --git a/docs/about/index.html b/docs/about/index.html index 92ece0b5d3..2048c87e38 100644 --- a/docs/about/index.html +++ b/docs/about/index.html @@ -8,7 +8,7 @@ - + @@ -37,6 +37,6 @@ (opens new window)

# About

Caliban is a project created by Pierre Ricadat aka @ghostdogpr (opens new window).

Current maintainers:

The name is inspired by the SF novel and tv series The Expanse (opens new window).

Thanks:

- + diff --git a/docs/assets/js/24.3b70fa72.js b/docs/assets/js/24.751a4ded.js similarity index 96% rename from docs/assets/js/24.3b70fa72.js rename to docs/assets/js/24.751a4ded.js index 64d7560be6..f6a0850c20 100644 --- a/docs/assets/js/24.3b70fa72.js +++ b/docs/assets/js/24.751a4ded.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[24],{306:function(t,a,s){"use strict";s.r(a);var e=s(14),r=Object(e.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"getting-started"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#getting-started"}},[t._v("#")]),t._v(" Getting Started")]),t._v(" "),a("p",[a("strong",[t._v("Caliban")]),t._v(" is a purely functional library for creating GraphQL servers and clients in Scala.")]),t._v(" "),a("p",[t._v("For more details on Caliban Client, see the "),a("RouterLink",{attrs:{to:"/docs/client.html"}},[t._v("dedicated section")]),t._v(". The rest of this page focuses on the backend part of the library.")],1),t._v(" "),a("p",[t._v("The design principles of Caliban are the following:")]),t._v(" "),a("ul",[a("li",[a("strong",[t._v("high performance")]),t._v(": while all public interfaces are pure and immutable, the library's internals are optimized for speed, offering the best performance of any Scala GraphQL library.")]),t._v(" "),a("li",[a("strong",[t._v("minimal amount of boilerplate")]),t._v(": you don't need to manually define schemas for every type in your API. Let the compiler handle the tedious work.")]),t._v(" "),a("li",[a("strong",[t._v("excellent interoperability")]),t._v(": out-of-the-box support for major HTTP server libraries ("),a("a",{attrs:{href:"https://http4s.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("http4s"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://doc.akka.io/docs/akka-http/current/index.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Akka HTTP"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/apache/incubator-pekko-http",target:"_blank",rel:"noopener noreferrer"}},[t._v("Pekko HTTP"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://www.playframework.com/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Play"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/dream11/zio-http",target:"_blank",rel:"noopener noreferrer"}},[t._v("ZIO HTTP"),a("OutboundLink")],1),t._v("), effect types (Future, "),a("a",{attrs:{href:"https://zio.dev/",target:"_blank",rel:"noopener noreferrer"}},[t._v("ZIO"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://typelevel.org/cats-effect/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Cats Effect"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://monix.io/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Monix"),a("OutboundLink")],1),t._v("), JSON libraries ("),a("a",{attrs:{href:"https://circe.github.io/circe/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Circe"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/plokhotnyuk/jsoniter-scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("Jsoniter"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/playframework/play-json",target:"_blank",rel:"noopener noreferrer"}},[t._v("Play Json"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/zio/zio-json",target:"_blank",rel:"noopener noreferrer"}},[t._v("ZIO Json"),a("OutboundLink")],1),t._v("), plus various integrations ("),a("a",{attrs:{href:"https://github.com/apollographql/apollo-tracing",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Tracing"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://www.apollographql.com/docs/federation/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Federation"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://tapir.softwaremill.com/en/latest/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Tapir"),a("OutboundLink")],1),t._v(", etc.) and more.")])]),t._v(" "),a("h2",{attrs:{id:"a-simple-schema"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#a-simple-schema"}},[t._v("#")]),t._v(" A simple schema")]),t._v(" "),a("p",[t._v("First, add the following dependency to your "),a("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),t._v("\n")])])]),a("p",[t._v("Creating a GraphQL API with Caliban is as simple as creating a case class in Scala.\nIndeed, the whole GraphQL schema will be derived from a case class hierarchy (its fields and the other types it references), and the resolver is just an instance of that case class.")]),t._v(" "),a("p",[t._v("Let's say we have a class "),a("code",[t._v("Character")]),t._v(" and 2 functions: "),a("code",[t._v("getCharacters")]),t._v(" and "),a("code",[t._v("getCharacter")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" age"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" getCharacters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Nil\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" getCharacter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n")])])]),a("p",[t._v("Let's create a case class named "),a("code",[t._v("Queries")]),t._v(" that will represent our API, with 2 fields named and modeled after the functions we want to expose.\nWe then create a value of this class that calls our actual functions. This is our resolver.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// schema")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" CharacterName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n character"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CharacterName "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// resolver")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" queries "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("getCharacters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" args "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" getCharacter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("The next step is creating our GraphQL API definition.")]),t._v(" "),a("p",[t._v("First, we wrap our query resolver inside a "),a("code",[t._v("RootResolver")]),t._v(", the root object that contains queries, mutations and subscriptions. Only queries are mandatory.\nThen we call the "),a("code",[t._v("graphQL")]),t._v(" function which will turn our simple resolver value into a GraphQL API definition.\nThe whole schema will be derived at compile time, meaning that if it compiles, it will be able to serve it.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("You can use "),a("code",[t._v("api.render")]),t._v(" to visualize the schema generated, in this case:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("age")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Queries")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("characters")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("character")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"serving-over-http"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#serving-over-http"}},[t._v("#")]),t._v(" Serving over HTTP")]),t._v(" "),a("p",[t._v("Once you have your API object, you can turn it into an interpreter ("),a("code",[t._v("api.interpreter")]),t._v(") and start processing requests ("),a("code",[t._v("interpreter.execute")]),t._v(").\nThe interpreter is not tied any web framework, so you are free to expose this function using the protocol and library of your choice.")]),t._v(" "),a("p",[t._v("The easiest (and most performant!) way to expose your API over HTTP is to use the optional "),a("code",[t._v("caliban-quick")]),t._v(" module based on "),a("a",{attrs:{href:"https://github.com/zio/zio-http",target:"_blank",rel:"noopener noreferrer"}},[t._v("zio-http"),a("OutboundLink")],1),t._v(".")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-quick"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),t._v("\n")])])]),a("p",[t._v("You can then serve your GraphQL API over HTTP using a single command:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:compile-only extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("quick"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_ "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// adds extension methods to `api`")]),t._v("\n\napi"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("unsafe"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("runServer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n port "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("8080")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n apiPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/api/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("And that's it - now you have a fully functional GraphQL server running on port 8080!")]),t._v(" "),a("h2",{attrs:{id:"interop-with-3rd-party-libraries"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#interop-with-3rd-party-libraries"}},[t._v("#")]),t._v(" Interop with 3rd-party libraries")]),t._v(" "),a("p",[t._v("If you have any specific server requirements or need to interop with other libraries, Caliban offers a wide range of modules to help you do that.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-http4s"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// routes for http4s")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-akka-http"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// routes for akka-http")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-pekko-http"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// routes for pekko-http")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-play"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// routes for play")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-cats"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// interop with cats-effect")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-monix"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// interop with monix")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-tapir"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// interop with tapir")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-federation"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// apollo federation")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-reporting"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// apollo schema reporting")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-tracing"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// open-telemetry")]),t._v("\n")])])]),a("h2",{attrs:{id:"where-to-go-next"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#where-to-go-next"}},[t._v("#")]),t._v(" Where to go next?")]),t._v(" "),a("p",[t._v("The rest of the documentation covers in details how to create "),a("RouterLink",{attrs:{to:"/docs/schema.html"}},[t._v("schemas")]),t._v(", "),a("RouterLink",{attrs:{to:"/docs/middleware.html"}},[t._v("customize")]),t._v(" and "),a("RouterLink",{attrs:{to:"/docs/optimization.html"}},[t._v("optimize")]),t._v(" query processing, "),a("RouterLink",{attrs:{to:"/docs/adapters.html"}},[t._v("expose")]),t._v(" APIs, and much more.")],1),t._v(" "),a("p",[t._v("If you'd like to see a more detailed version of this tutorial, check out this "),a("a",{attrs:{href:"https://blog.pierre-ricadat.com/a-beginners-guide-to-graphql-in-scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("Beginner's Guide to GraphQL in Scala"),a("OutboundLink")],1),t._v(".\nIf you prefer looking at some code first, check "),a("a",{attrs:{href:"https://ghostdogpr.github.io/caliban/docs/examples.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("this list of examples"),a("OutboundLink")],1),t._v(".")]),t._v(" "),a("p",[t._v("If you have any questions, just come to the "),a("a",{attrs:{href:"https://discord.gg/EYpumuv",target:"_blank",rel:"noopener noreferrer"}},[t._v("Discord channel"),a("OutboundLink")],1),t._v("!")])])}),[],!1,null,null,null);a.default=r.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[24],{306:function(t,a,s){"use strict";s.r(a);var e=s(14),r=Object(e.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"getting-started"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#getting-started"}},[t._v("#")]),t._v(" Getting Started")]),t._v(" "),a("p",[a("strong",[t._v("Caliban")]),t._v(" is a purely functional library for creating GraphQL servers and clients in Scala.")]),t._v(" "),a("p",[t._v("For more details on Caliban Client, see the "),a("RouterLink",{attrs:{to:"/docs/client.html"}},[t._v("dedicated section")]),t._v(". The rest of this page focuses on the backend part of the library.")],1),t._v(" "),a("p",[t._v("The design principles of Caliban are the following:")]),t._v(" "),a("ul",[a("li",[a("strong",[t._v("high performance")]),t._v(": while all public interfaces are pure and immutable, the library's internals are optimized for speed, offering the best performance of any Scala GraphQL library.")]),t._v(" "),a("li",[a("strong",[t._v("minimal amount of boilerplate")]),t._v(": you don't need to manually define schemas for every type in your API. Let the compiler handle the tedious work.")]),t._v(" "),a("li",[a("strong",[t._v("excellent interoperability")]),t._v(": out-of-the-box support for major HTTP server libraries ("),a("a",{attrs:{href:"https://http4s.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("http4s"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://doc.akka.io/docs/akka-http/current/index.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Akka HTTP"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/apache/incubator-pekko-http",target:"_blank",rel:"noopener noreferrer"}},[t._v("Pekko HTTP"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://www.playframework.com/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Play"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/dream11/zio-http",target:"_blank",rel:"noopener noreferrer"}},[t._v("ZIO HTTP"),a("OutboundLink")],1),t._v("), effect types (Future, "),a("a",{attrs:{href:"https://zio.dev/",target:"_blank",rel:"noopener noreferrer"}},[t._v("ZIO"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://typelevel.org/cats-effect/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Cats Effect"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://monix.io/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Monix"),a("OutboundLink")],1),t._v("), JSON libraries ("),a("a",{attrs:{href:"https://circe.github.io/circe/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Circe"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/plokhotnyuk/jsoniter-scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("Jsoniter"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/playframework/play-json",target:"_blank",rel:"noopener noreferrer"}},[t._v("Play Json"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/zio/zio-json",target:"_blank",rel:"noopener noreferrer"}},[t._v("ZIO Json"),a("OutboundLink")],1),t._v("), plus various integrations ("),a("a",{attrs:{href:"https://github.com/apollographql/apollo-tracing",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Tracing"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://www.apollographql.com/docs/federation/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Federation"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://tapir.softwaremill.com/en/latest/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Tapir"),a("OutboundLink")],1),t._v(", etc.) and more.")])]),t._v(" "),a("h2",{attrs:{id:"a-simple-schema"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#a-simple-schema"}},[t._v("#")]),t._v(" A simple schema")]),t._v(" "),a("p",[t._v("First, add the following dependency to your "),a("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),t._v("\n")])])]),a("p",[t._v("Creating a GraphQL API with Caliban is as simple as creating a case class in Scala.\nIndeed, the whole GraphQL schema will be derived from a case class hierarchy (its fields and the other types it references), and the resolver is just an instance of that case class.")]),t._v(" "),a("p",[t._v("Let's say we have a class "),a("code",[t._v("Character")]),t._v(" and 2 functions: "),a("code",[t._v("getCharacters")]),t._v(" and "),a("code",[t._v("getCharacter")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" age"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" getCharacters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Nil\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" getCharacter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n")])])]),a("p",[t._v("Let's create a case class named "),a("code",[t._v("Queries")]),t._v(" that will represent our API, with 2 fields named and modeled after the functions we want to expose.\nWe then create a value of this class that calls our actual functions. This is our resolver.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// schema")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" CharacterName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n character"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CharacterName "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// resolver")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" queries "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("getCharacters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" args "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" getCharacter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("The next step is creating our GraphQL API definition.")]),t._v(" "),a("p",[t._v("First, we wrap our query resolver inside a "),a("code",[t._v("RootResolver")]),t._v(", the root object that contains queries, mutations and subscriptions. Only queries are mandatory.\nThen we call the "),a("code",[t._v("graphQL")]),t._v(" function which will turn our simple resolver value into a GraphQL API definition.\nThe whole schema will be derived at compile time, meaning that if it compiles, it will be able to serve it.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("You can use "),a("code",[t._v("api.render")]),t._v(" to visualize the schema generated, in this case:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("age")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Queries")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("characters")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("character")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"serving-over-http"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#serving-over-http"}},[t._v("#")]),t._v(" Serving over HTTP")]),t._v(" "),a("p",[t._v("Once you have your API object, you can turn it into an interpreter ("),a("code",[t._v("api.interpreter")]),t._v(") and start processing requests ("),a("code",[t._v("interpreter.execute")]),t._v(").\nThe interpreter is not tied any web framework, so you are free to expose this function using the protocol and library of your choice.")]),t._v(" "),a("p",[t._v("The easiest (and most performant!) way to expose your API over HTTP is to use the optional "),a("code",[t._v("caliban-quick")]),t._v(" module based on "),a("a",{attrs:{href:"https://github.com/zio/zio-http",target:"_blank",rel:"noopener noreferrer"}},[t._v("zio-http"),a("OutboundLink")],1),t._v(".")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-quick"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),t._v("\n")])])]),a("p",[t._v("You can then serve your GraphQL API over HTTP using a single command:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:compile-only extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("quick"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_ "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// adds extension methods to `api`")]),t._v("\n\napi"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("unsafe"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("runServer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n port "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("8080")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n apiPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/api/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("And that's it - now you have a fully functional GraphQL server running on port 8080!")]),t._v(" "),a("h2",{attrs:{id:"interop-with-3rd-party-libraries"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#interop-with-3rd-party-libraries"}},[t._v("#")]),t._v(" Interop with 3rd-party libraries")]),t._v(" "),a("p",[t._v("If you have any specific server requirements or need to interop with other libraries, Caliban offers a wide range of modules to help you do that.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-http4s"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// routes for http4s")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-akka-http"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// routes for akka-http")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-pekko-http"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// routes for pekko-http")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-play"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// routes for play")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-cats"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// interop with cats-effect")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-monix"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// interop with monix")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-tapir"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// interop with tapir")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-federation"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// apollo federation")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-reporting"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// apollo schema reporting")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-tracing"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// open-telemetry")]),t._v("\n")])])]),a("h2",{attrs:{id:"where-to-go-next"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#where-to-go-next"}},[t._v("#")]),t._v(" Where to go next?")]),t._v(" "),a("p",[t._v("The rest of the documentation covers in details how to create "),a("RouterLink",{attrs:{to:"/docs/schema.html"}},[t._v("schemas")]),t._v(", "),a("RouterLink",{attrs:{to:"/docs/middleware.html"}},[t._v("customize")]),t._v(" and "),a("RouterLink",{attrs:{to:"/docs/optimization.html"}},[t._v("optimize")]),t._v(" query processing, "),a("RouterLink",{attrs:{to:"/docs/adapters.html"}},[t._v("expose")]),t._v(" APIs, and much more.")],1),t._v(" "),a("p",[t._v("If you'd like to see a more detailed version of this tutorial, check out this "),a("a",{attrs:{href:"https://blog.pierre-ricadat.com/a-beginners-guide-to-graphql-in-scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("Beginner's Guide to GraphQL in Scala"),a("OutboundLink")],1),t._v(".\nIf you prefer looking at some code first, check "),a("a",{attrs:{href:"https://ghostdogpr.github.io/caliban/docs/examples.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("this list of examples"),a("OutboundLink")],1),t._v(".")]),t._v(" "),a("p",[t._v("If you have any questions, just come to the "),a("a",{attrs:{href:"https://discord.gg/EYpumuv",target:"_blank",rel:"noopener noreferrer"}},[t._v("Discord channel"),a("OutboundLink")],1),t._v("!")])])}),[],!1,null,null,null);a.default=r.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/25.84e7c3a0.js b/docs/assets/js/25.a67f9e7a.js similarity index 99% rename from docs/assets/js/25.84e7c3a0.js rename to docs/assets/js/25.a67f9e7a.js index 5691a227f6..e5693dfccc 100644 --- a/docs/assets/js/25.84e7c3a0.js +++ b/docs/assets/js/25.a67f9e7a.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[25],{307:function(t,a,e){"use strict";e.r(a);var r=e(14),s=Object(r.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"http-adapters"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#http-adapters"}},[t._v("#")]),t._v(" Http Adapters")]),t._v(" "),a("p",[t._v('Once you have an interpreter able to execute GraphQL queries, you usually want to expose it using an HTTP API.\nCaliban comes with a few "ready-to-use" components (called "adapters") to expose your API with the most popular HTTP libraries.')]),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("`QuickAdapter`")]),t._v(" "),a("p",[t._v("Starting with v2.4.3, Caliban provides the opinionated "),a("RouterLink",{attrs:{to:"/docs/adapters.html#high-performance-quickadapter"}},[t._v("QuickAdapter")]),t._v("\nthat favours ease-of-use and performance at the expense of customizability.")],1),t._v(" "),a("p",[t._v("If you want the best possible performance, make sure to check it out!")])]),t._v(" "),a("h2",{attrs:{id:"built-in-tapir-adapters"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#built-in-tapir-adapters"}},[t._v("#")]),t._v(" Built-in tapir adapters")]),t._v(" "),a("p",[t._v("Under the hood, adapters use the "),a("a",{attrs:{href:"https://tapir.softwaremill.com/en/latest/",target:"_blank",rel:"noopener noreferrer"}},[t._v("tapir"),a("OutboundLink")],1),t._v(" library, so you can easily create a custom adapter with anything that tapir supports.")]),t._v(" "),a("p",[t._v("The following adapters are provided:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("Http4sAdapter")]),t._v(" exposes a route for http4s.")]),t._v(" "),a("li",[a("code",[t._v("PlayHttpAdapter")]),t._v(" exposes a route for play.")]),t._v(" "),a("li",[a("code",[t._v("AkkaHttpAdapter")]),t._v(" exposes a route for akka.")]),t._v(" "),a("li",[a("code",[t._v("PekkoHttpAdapter")]),t._v(" exposes a route for pekko.")])]),t._v(" "),a("p",[t._v("To use them, you first need to transform your "),a("code",[t._v("GraphQLInterpreter")]),t._v(" obtained from "),a("code",[t._v("api.interpreter")]),t._v(" into a new type of interpreter that supports the protocol you want to use.\nThere are 3 of them:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("HttpInterpreter")]),t._v(" follows the "),a("a",{attrs:{href:"https://graphql.org/learn/serving-over-http/#http-methods-headers-and-body",target:"_blank",rel:"noopener noreferrer"}},[t._v("standard GraphQL protocol"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("code",[t._v("HttpUploadInterpreter")]),t._v(" follows the "),a("a",{attrs:{href:"https://github.com/jaydenseric/graphql-multipart-request-spec",target:"_blank",rel:"noopener noreferrer"}},[t._v("GraphQL multipart request protocol"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("code",[t._v("WebSocketInterpreter")]),t._v(" follows the "),a("a",{attrs:{href:"https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md",target:"_blank",rel:"noopener noreferrer"}},[t._v("GraphQL WebSocket protocol"),a("OutboundLink")],1)])]),t._v(" "),a("p",[t._v("These interpreters expose 2 powerful methods:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("configure")]),t._v(" takes a "),a("code",[t._v("Configurator[R]")]),t._v(" which is an alias for "),a("code",[t._v("URIO[R & Scope, Unit]")]),t._v(".\nIt allows configuring the interpreter by running an effect that will run for each request and that can modify the configuration of the running fiber. Built-in configurators such as "),a("code",[t._v("Configurator.setSkipValidation")]),t._v(", "),a("code",[t._v("Configurator.setEnableIntrospection")]),t._v(" and "),a("code",[t._v("Configurator.setQueryExecution")]),t._v(" let you dynamically change the configuration of the interpreter.")]),t._v(" "),a("li",[a("code",[t._v("intercept")]),t._v(" takes an "),a("code",[t._v("Interceptor[-R1, +R]")]),t._v(" which is an alias for "),a("code",[t._v("ZLayer[R1 & ServerRequest, TapirResponse, R]")]),t._v(".\nIt is basically a more powerful version of "),a("code",[t._v("configure")]),t._v(" that gives you access to the incoming request ("),a("code",[t._v("ServerRequest")]),t._v(") and lets you modify the environment of the interpreter (from "),a("code",[t._v("R")]),t._v(" to "),a("code",[t._v("R1")]),t._v("). A typical use case would be to extract an authentication token from the request and eliminate the authentication requirement from the environment if the token is valid. See an example "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/blob/series/2.x/examples/src/main/scala/example/akkahttp/AuthExampleApp.scala#L51",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1),t._v(".")])]),t._v(" "),a("p",[t._v("In addition to that, the "),a("code",[t._v("WebSocketInterpreter")]),t._v(" constructor comes with 2 optional parameters:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("keepAliveInterval")]),t._v(" (default: empty) defines the interval for the server to send keep alive messages to the client")]),t._v(" "),a("li",[a("code",[t._v("webSocketHooks")]),t._v(" (default: empty) gives you some hooks around the WebSocket lifecycle (useful for authentication)")])]),t._v(" "),a("p",[t._v("Once your interpreter is correctly configured, you can use one of these 3 functions exposed by each built-in adapter:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("makeHttpService")]),t._v(" turns an "),a("code",[t._v("HttpInterpreter")]),t._v(" into a route for the corresponding library")]),t._v(" "),a("li",[a("code",[t._v("makeHttpUploadService")]),t._v(" turns an "),a("code",[t._v("HttpUploadInterpreter")]),t._v(" into a route for the corresponding library")]),t._v(" "),a("li",[a("code",[t._v("makeWebSocketService")]),t._v(" turns a "),a("code",[t._v("WebSocketInterpreter")]),t._v(" into a route for the corresponding library")])]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" graphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("AuthToken"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// turn our GraphQL interpreter into an HttpInterpreter")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" noAuthInterpreter"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" HttpInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("AuthToken"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" HttpInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("graphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// define authentication logic (from a ServerRequest, fail or build an AuthToken)")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" auth"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ZLayer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ServerRequest"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" TapirResponse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" AuthToken"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// pass our interceptor to eliminate the AuthToken requirement from the environment")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" authInterpreter"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" HttpUploadInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" httpInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("intercept"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("auth"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// get our route for Akka Http")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" route "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" AkkaHttpAdapter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("default"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("makeHttpService"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("authInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("Want to use something else? Check "),a("a",{attrs:{href:"#make-your-own-adapter"}},[t._v("make your own adapter section")]),t._v("!")]),t._v(" "),a("p",[t._v("Make sure to check the "),a("RouterLink",{attrs:{to:"/docs/examples.html"}},[t._v("examples")]),t._v(" to see the adapters in action.")],1),t._v(" "),a("h2",{attrs:{id:"make-your-own-adapter"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#make-your-own-adapter"}},[t._v("#")]),t._v(" Make your own adapter")]),t._v(" "),a("p",[t._v("All existing adapters are actually using a common adapter under the hood, called "),a("code",[t._v("TapirAdapter")]),t._v(".")]),t._v(" "),a("p",[t._v("This adapter, available in the "),a("code",[t._v("caliban-tapir")]),t._v(" dependency which has the same 3 methods "),a("code",[t._v("makeHttpService")]),t._v(", "),a("code",[t._v("makeHttpUploadService")]),t._v(" and "),a("code",[t._v("makeWebSocketService")]),t._v(".")]),t._v(" "),a("p",[t._v("The main differences between these and the methods from the built-in adapters is that they return one or several tapir "),a("code",[t._v("ServerEndpoint")]),t._v(",\nwhich you can then pass to a tapir interpreter. The returned "),a("code",[t._v("ServerEndpoint")]),t._v(" use "),a("code",[t._v("RIO[R, *]")]),t._v(" as an effect type, but you can easily transform it to another effect type. A helper "),a("code",[t._v("convertHttpEndpointToFuture")]),t._v(" allows converting the effect type to a scala "),a("code",[t._v("Future")]),t._v(" (this is used in the Akka, Pekko, and Play interpreters).")]),t._v(" "),a("h2",{attrs:{id:"high-performance-quickadapter"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#high-performance-quickadapter"}},[t._v("#")]),t._v(" High-performance "),a("code",[t._v("QuickAdapter")])]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("QuickAdapter")]),t._v(" requires minimal setup and uses "),a("a",{attrs:{href:"https://github.com/zio/zio-http",target:"_blank",rel:"noopener noreferrer"}},[t._v("zio-http"),a("OutboundLink")],1),t._v("\nwithout tapir in order to provide the best possible performance.")]),t._v(" "),a("h3",{attrs:{id:"usage"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#usage"}},[t._v("#")]),t._v(" Usage")]),t._v(" "),a("p",[t._v("In order to use it, just add the following to your "),a("code",[t._v("build.sbt")]),t._v(" file (no other dependencies required!):")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("libraryDependencies "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-quick"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),t._v("\n")])])]),a("p",[t._v("By adding "),a("code",[t._v("import caliban.quick._")]),t._v(", we expose a few convenient extension methods on our "),a("code",[t._v("GraphQL")]),t._v(" api.\nFor example, we can serve our GraphQL api with minimal setup via a single command:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:compile-only extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("quick"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\napi"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("unsafe"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("runServer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n port "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("8080")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n apiPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/api/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n graphiqlPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/graphiql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n uploadPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/upload/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// optional, for enabling GraphQL uploads")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("Alternatively, you can also create a zio-http "),a("code",[t._v("Handler")]),t._v(" and manually compose it into an app:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:compile-only extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("quick"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n handlers "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("handlers\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Alternatively, without imported syntax:")]),t._v("\n handlers2 "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("QuickAdapter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("handlers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Creates a handler which serves the GraphiQL API from CDN")]),t._v("\n graphiql "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" GraphiQLHandler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("handler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("apiPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/api/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" graphiqlPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/graphiql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n app "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Routes"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Method"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ANY "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"api"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"graphql"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" handlers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Method"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("GET "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"graphiql"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" graphiql"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Method"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("POST "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"upload"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"graphql"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" handlers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("upload\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Add more routes, apply middleware, etc.")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" app"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("serve"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("provide"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Server"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("defaultWithPort"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("8080")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h3",{attrs:{id:"customization"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#customization"}},[t._v("#")]),t._v(" Customization")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("QuickAdapter")]),t._v(" exposes the following methods that allow you to customize the server or apply middleware to the routes:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("configure")]),t._v(" which takes a "),a("code",[t._v("Configurator[R]")]),t._v(" "),a("RouterLink",{attrs:{to:"/docs/adapters.html#built-in-tapir-adapters"}},[t._v("similar to the tapir-based adapters")])],1),t._v(" "),a("li",[a("code",[t._v("handlers")]),t._v(" which returns a "),a("code",[t._v("QuickHandlers[R]")]),t._v(" which contains individual handlers to manually construct routes.\nNote that this handler is only for the api routes. To construct the graphiql handler use "),a("code",[t._v("caliban.GraphiQLHandler.handler")]),t._v(".")])]),t._v(" "),a("p",[t._v("For more info on customization and middleware, check out the "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/quick",target:"_blank",rel:"noopener noreferrer"}},[t._v("adapter examples"),a("OutboundLink")],1),t._v("!")])])}),[],!1,null,null,null);a.default=s.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[25],{307:function(t,a,e){"use strict";e.r(a);var r=e(14),s=Object(r.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"http-adapters"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#http-adapters"}},[t._v("#")]),t._v(" Http Adapters")]),t._v(" "),a("p",[t._v('Once you have an interpreter able to execute GraphQL queries, you usually want to expose it using an HTTP API.\nCaliban comes with a few "ready-to-use" components (called "adapters") to expose your API with the most popular HTTP libraries.')]),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("`QuickAdapter`")]),t._v(" "),a("p",[t._v("Starting with v2.4.3, Caliban provides the opinionated "),a("RouterLink",{attrs:{to:"/docs/adapters.html#high-performance-quickadapter"}},[t._v("QuickAdapter")]),t._v("\nthat favours ease-of-use and performance at the expense of customizability.")],1),t._v(" "),a("p",[t._v("If you want the best possible performance, make sure to check it out!")])]),t._v(" "),a("h2",{attrs:{id:"built-in-tapir-adapters"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#built-in-tapir-adapters"}},[t._v("#")]),t._v(" Built-in tapir adapters")]),t._v(" "),a("p",[t._v("Under the hood, adapters use the "),a("a",{attrs:{href:"https://tapir.softwaremill.com/en/latest/",target:"_blank",rel:"noopener noreferrer"}},[t._v("tapir"),a("OutboundLink")],1),t._v(" library, so you can easily create a custom adapter with anything that tapir supports.")]),t._v(" "),a("p",[t._v("The following adapters are provided:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("Http4sAdapter")]),t._v(" exposes a route for http4s.")]),t._v(" "),a("li",[a("code",[t._v("PlayHttpAdapter")]),t._v(" exposes a route for play.")]),t._v(" "),a("li",[a("code",[t._v("AkkaHttpAdapter")]),t._v(" exposes a route for akka.")]),t._v(" "),a("li",[a("code",[t._v("PekkoHttpAdapter")]),t._v(" exposes a route for pekko.")])]),t._v(" "),a("p",[t._v("To use them, you first need to transform your "),a("code",[t._v("GraphQLInterpreter")]),t._v(" obtained from "),a("code",[t._v("api.interpreter")]),t._v(" into a new type of interpreter that supports the protocol you want to use.\nThere are 3 of them:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("HttpInterpreter")]),t._v(" follows the "),a("a",{attrs:{href:"https://graphql.org/learn/serving-over-http/#http-methods-headers-and-body",target:"_blank",rel:"noopener noreferrer"}},[t._v("standard GraphQL protocol"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("code",[t._v("HttpUploadInterpreter")]),t._v(" follows the "),a("a",{attrs:{href:"https://github.com/jaydenseric/graphql-multipart-request-spec",target:"_blank",rel:"noopener noreferrer"}},[t._v("GraphQL multipart request protocol"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("code",[t._v("WebSocketInterpreter")]),t._v(" follows the "),a("a",{attrs:{href:"https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md",target:"_blank",rel:"noopener noreferrer"}},[t._v("GraphQL WebSocket protocol"),a("OutboundLink")],1)])]),t._v(" "),a("p",[t._v("These interpreters expose 2 powerful methods:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("configure")]),t._v(" takes a "),a("code",[t._v("Configurator[R]")]),t._v(" which is an alias for "),a("code",[t._v("URIO[R & Scope, Unit]")]),t._v(".\nIt allows configuring the interpreter by running an effect that will run for each request and that can modify the configuration of the running fiber. Built-in configurators such as "),a("code",[t._v("Configurator.setSkipValidation")]),t._v(", "),a("code",[t._v("Configurator.setEnableIntrospection")]),t._v(" and "),a("code",[t._v("Configurator.setQueryExecution")]),t._v(" let you dynamically change the configuration of the interpreter.")]),t._v(" "),a("li",[a("code",[t._v("intercept")]),t._v(" takes an "),a("code",[t._v("Interceptor[-R1, +R]")]),t._v(" which is an alias for "),a("code",[t._v("ZLayer[R1 & ServerRequest, TapirResponse, R]")]),t._v(".\nIt is basically a more powerful version of "),a("code",[t._v("configure")]),t._v(" that gives you access to the incoming request ("),a("code",[t._v("ServerRequest")]),t._v(") and lets you modify the environment of the interpreter (from "),a("code",[t._v("R")]),t._v(" to "),a("code",[t._v("R1")]),t._v("). A typical use case would be to extract an authentication token from the request and eliminate the authentication requirement from the environment if the token is valid. See an example "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/blob/series/2.x/examples/src/main/scala/example/akkahttp/AuthExampleApp.scala#L51",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1),t._v(".")])]),t._v(" "),a("p",[t._v("In addition to that, the "),a("code",[t._v("WebSocketInterpreter")]),t._v(" constructor comes with 2 optional parameters:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("keepAliveInterval")]),t._v(" (default: empty) defines the interval for the server to send keep alive messages to the client")]),t._v(" "),a("li",[a("code",[t._v("webSocketHooks")]),t._v(" (default: empty) gives you some hooks around the WebSocket lifecycle (useful for authentication)")])]),t._v(" "),a("p",[t._v("Once your interpreter is correctly configured, you can use one of these 3 functions exposed by each built-in adapter:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("makeHttpService")]),t._v(" turns an "),a("code",[t._v("HttpInterpreter")]),t._v(" into a route for the corresponding library")]),t._v(" "),a("li",[a("code",[t._v("makeHttpUploadService")]),t._v(" turns an "),a("code",[t._v("HttpUploadInterpreter")]),t._v(" into a route for the corresponding library")]),t._v(" "),a("li",[a("code",[t._v("makeWebSocketService")]),t._v(" turns a "),a("code",[t._v("WebSocketInterpreter")]),t._v(" into a route for the corresponding library")])]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" graphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("AuthToken"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// turn our GraphQL interpreter into an HttpInterpreter")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" noAuthInterpreter"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" HttpInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("AuthToken"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" HttpInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("graphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// define authentication logic (from a ServerRequest, fail or build an AuthToken)")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" auth"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ZLayer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ServerRequest"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" TapirResponse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" AuthToken"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// pass our interceptor to eliminate the AuthToken requirement from the environment")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" authInterpreter"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" HttpUploadInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" httpInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("intercept"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("auth"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// get our route for Akka Http")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" route "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" AkkaHttpAdapter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("default"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("makeHttpService"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("authInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("Want to use something else? Check "),a("a",{attrs:{href:"#make-your-own-adapter"}},[t._v("make your own adapter section")]),t._v("!")]),t._v(" "),a("p",[t._v("Make sure to check the "),a("RouterLink",{attrs:{to:"/docs/examples.html"}},[t._v("examples")]),t._v(" to see the adapters in action.")],1),t._v(" "),a("h2",{attrs:{id:"make-your-own-adapter"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#make-your-own-adapter"}},[t._v("#")]),t._v(" Make your own adapter")]),t._v(" "),a("p",[t._v("All existing adapters are actually using a common adapter under the hood, called "),a("code",[t._v("TapirAdapter")]),t._v(".")]),t._v(" "),a("p",[t._v("This adapter, available in the "),a("code",[t._v("caliban-tapir")]),t._v(" dependency which has the same 3 methods "),a("code",[t._v("makeHttpService")]),t._v(", "),a("code",[t._v("makeHttpUploadService")]),t._v(" and "),a("code",[t._v("makeWebSocketService")]),t._v(".")]),t._v(" "),a("p",[t._v("The main differences between these and the methods from the built-in adapters is that they return one or several tapir "),a("code",[t._v("ServerEndpoint")]),t._v(",\nwhich you can then pass to a tapir interpreter. The returned "),a("code",[t._v("ServerEndpoint")]),t._v(" use "),a("code",[t._v("RIO[R, *]")]),t._v(" as an effect type, but you can easily transform it to another effect type. A helper "),a("code",[t._v("convertHttpEndpointToFuture")]),t._v(" allows converting the effect type to a scala "),a("code",[t._v("Future")]),t._v(" (this is used in the Akka, Pekko, and Play interpreters).")]),t._v(" "),a("h2",{attrs:{id:"high-performance-quickadapter"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#high-performance-quickadapter"}},[t._v("#")]),t._v(" High-performance "),a("code",[t._v("QuickAdapter")])]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("QuickAdapter")]),t._v(" requires minimal setup and uses "),a("a",{attrs:{href:"https://github.com/zio/zio-http",target:"_blank",rel:"noopener noreferrer"}},[t._v("zio-http"),a("OutboundLink")],1),t._v("\nwithout tapir in order to provide the best possible performance.")]),t._v(" "),a("h3",{attrs:{id:"usage"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#usage"}},[t._v("#")]),t._v(" Usage")]),t._v(" "),a("p",[t._v("In order to use it, just add the following to your "),a("code",[t._v("build.sbt")]),t._v(" file (no other dependencies required!):")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("libraryDependencies "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-quick"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),t._v("\n")])])]),a("p",[t._v("By adding "),a("code",[t._v("import caliban.quick._")]),t._v(", we expose a few convenient extension methods on our "),a("code",[t._v("GraphQL")]),t._v(" api.\nFor example, we can serve our GraphQL api with minimal setup via a single command:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:compile-only extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("quick"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\napi"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("unsafe"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("runServer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n port "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("8080")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n apiPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/api/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n graphiqlPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/graphiql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n uploadPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/upload/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// optional, for enabling GraphQL uploads")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("Alternatively, you can also create a zio-http "),a("code",[t._v("Handler")]),t._v(" and manually compose it into an app:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:compile-only extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("quick"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n handlers "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("handlers\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Alternatively, without imported syntax:")]),t._v("\n handlers2 "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("QuickAdapter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("handlers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Creates a handler which serves the GraphiQL API from CDN")]),t._v("\n graphiql "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" GraphiQLHandler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("handler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("apiPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/api/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" graphiqlPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/graphiql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n app "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Routes"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Method"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ANY "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"api"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"graphql"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" handlers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Method"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("GET "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"graphiql"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" graphiql"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Method"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("POST "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"upload"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"graphql"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" handlers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("upload\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Add more routes, apply middleware, etc.")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" app"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("serve"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("provide"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Server"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("defaultWithPort"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("8080")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h3",{attrs:{id:"customization"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#customization"}},[t._v("#")]),t._v(" Customization")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("QuickAdapter")]),t._v(" exposes the following methods that allow you to customize the server or apply middleware to the routes:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("configure")]),t._v(" which takes a "),a("code",[t._v("Configurator[R]")]),t._v(" "),a("RouterLink",{attrs:{to:"/docs/adapters.html#built-in-tapir-adapters"}},[t._v("similar to the tapir-based adapters")])],1),t._v(" "),a("li",[a("code",[t._v("handlers")]),t._v(" which returns a "),a("code",[t._v("QuickHandlers[R]")]),t._v(" which contains individual handlers to manually construct routes.\nNote that this handler is only for the api routes. To construct the graphiql handler use "),a("code",[t._v("caliban.GraphiQLHandler.handler")]),t._v(".")])]),t._v(" "),a("p",[t._v("For more info on customization and middleware, check out the "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/quick",target:"_blank",rel:"noopener noreferrer"}},[t._v("adapter examples"),a("OutboundLink")],1),t._v("!")])])}),[],!1,null,null,null);a.default=s.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/26.75721902.js b/docs/assets/js/26.a75153e4.js similarity index 99% rename from docs/assets/js/26.75721902.js rename to docs/assets/js/26.a75153e4.js index 0358c03c81..9edfb3334b 100644 --- a/docs/assets/js/26.75721902.js +++ b/docs/assets/js/26.a75153e4.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[26],{309:function(e,a,t){"use strict";t.r(a);var n=t(14),s=Object(n.a)({},(function(){var e=this,a=e._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[a("h1",{attrs:{id:"code-generation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#code-generation"}},[e._v("#")]),e._v(" Code Generation")]),e._v(" "),a("p",[e._v("Caliban provides two sbt plugins to generate your client(s) code.")]),e._v(" "),a("p",[e._v("The first one, named "),a("code",[e._v("CalibanPlugin")]),e._v(", allows you to generate the client code from a schema file or from a server URL, manually or automatically.")]),e._v(" "),a("p",[e._v("The second one, named "),a("code",[e._v("CompileTimeCalibanPlugin")]),e._v(', allows you to generate the client code from your server code.\nThis second "meta" plugin is actually made of two "concrete" plugins, '),a("code",[e._v("CompileTimeCalibanServerPlugin")]),e._v(" and "),a("code",[e._v("CompileTimeCalibanClientPlugin")]),e._v(", that you'll\nboth need to configure in your project to be able to generate you Caliban client code from your Caliban server code.")]),e._v(" "),a("p",[e._v("To use any of these two plugins, you'll first need to add following dependency to your "),a("code",[e._v("project/plugins.sbt")]),e._v(" file:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[e._v("addSbtPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"com.github.ghostdogpr"')]),e._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("%")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"caliban-codegen-sbt"')]),e._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("%")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"2.8.1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("h2",{attrs:{id:"calibanplugin"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#calibanplugin"}},[e._v("#")]),e._v(" CalibanPlugin")]),e._v(" "),a("p",[e._v("The first step for building GraphQL queries with "),a("code",[e._v("caliban-client")]),e._v(" is to generate boilerplate code from a GraphQL schema. For that, you need a file containing your schema (if your backend uses "),a("code",[e._v("caliban")]),e._v(", you can get it by calling "),a("code",[e._v("GraphQL#render")]),e._v(" on your API).")]),e._v(" "),a("p",[e._v("And enable it in your "),a("code",[e._v("build.sbt")]),e._v(" file:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[e._v("enablePlugins"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("CalibanPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("h3",{attrs:{id:"from-a-schema-file"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#from-a-schema-file"}},[e._v("#")]),e._v(" From a schema file")]),e._v(" "),a("p",[e._v("At this point, the "),a("code",[e._v("caliban")]),e._v(" command will cause any files in "),a("code",[e._v("src/main/graphql")]),e._v(" to be translated into a Caliban-generated client library. This happens automatically any time you "),a("code",[e._v("compile")]),e._v(".")]),e._v(" "),a("p",[e._v("By default, all clients are generated with the same client name as the source file, in the "),a("code",[e._v("caliban")]),e._v(" top-level package.")]),e._v(" "),a("p",[e._v("In order to supply more configuration options to the code generator, you can use the "),a("code",[e._v("calibanSettings")]),e._v(" sbt setting, combined with the "),a("code",[e._v("calibanSetting")]),e._v(" function to scope the settings to a particular file:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[e._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[e._v('// The `file("Service.graphql")` is a path suffix for some file in `src/main/graphql`')]),e._v("\n Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" caliban "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" calibanSettings "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("+=")]),e._v(" calibanSetting"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"Service.graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n cs "),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("=>")]),e._v("\n cs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("packageName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"com.example.graphql.client"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("scalarMapping"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"LanguageCode"')]),e._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("->")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"com.example.models.LanguageCode"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("scalarMapping"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"Timestamp"')]),e._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("->")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"java.sql.Timestamp"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"DayOfWeek"')]),e._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("->")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"java.time.DayOfWeek"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"IntRange"')]),e._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("->")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"com.github.tminglei.slickpg.Range[Int]"')]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("imports"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"com.example.graphql.client.implicits._"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("p",[e._v("The path where the generator will look for schemas can be customized by overriding the "),a("code",[e._v("calibanSources")]),e._v(" settings:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[e._v("Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" caliban "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" calibanSources "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v(":")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"caliban"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("p",[e._v("If you want to cherry-pick certain files yourself, you can override that as well with an explicit "),a("code",[e._v("caliban / sources")]),e._v(" entry:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[e._v("Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" caliban "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" sources "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v(":")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"caliban"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"Service.graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("p",[e._v("For every entry in "),a("code",[e._v("calibanSettings")]),e._v(" for the same file, a separate client (or "),a("RouterLink",{attrs:{to:"/docs/schema.html#code-generation"}},[e._v("schema")]),e._v(", depending on the entry's "),a("code",[e._v("genType")]),e._v(" value) will be generated.")],1),e._v(" "),a("h3",{attrs:{id:"from-a-server-url"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#from-a-server-url"}},[e._v("#")]),e._v(" From a server URL")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("calibanSetting")]),e._v(" function also permits generating clients for supplied "),a("code",[e._v("url")]),e._v("'s:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[e._v(" Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" caliban "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" calibanSettings "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("+=")]),e._v(" calibanSetting"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("url"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"http://my-example-service/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n cs "),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("=>")]),e._v("\n cs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("clientName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"ExampleServiceClient"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("packageName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"com.example.graphql.client"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("h3",{attrs:{id:"generation-settings"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#generation-settings"}},[e._v("#")]),e._v(" Generation settings")]),e._v(" "),a("p",[e._v("The settings available on the "),a("code",[e._v("cs")]),e._v(" ("),a("code",[e._v("CalibanSettings")]),e._v(") builder are:")]),e._v(" "),a("ul",[a("li",[a("code",[e._v("packageName")]),e._v(": The package in which the code will be generated (default: "),a("code",[e._v("caliban")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("scalafmtPath")]),e._v(": Path to a scalafmt config file (default: "),a("code",[e._v(".scalafmt.conf")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("genView")]),e._v(": If true, will generate a case class and helper method to select all fields on an object (default: "),a("code",[e._v("false")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("scalarMappings")]),e._v(": A mapping from GraphQL scalar types to JVM types, as unknown scalar types are represented as "),a("code",[e._v("String")]),e._v(" by default.")]),e._v(" "),a("li",[a("code",[e._v("imports")]),e._v(": A list of imports to be added at the top of the generated code.")]),e._v(" "),a("li",[a("code",[e._v("splitFiles")]),e._v(": Whether to split the generated code into multiple files (default: "),a("code",[e._v("false")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("enableFmt")]),e._v(": Enable code formatting with scalafmt (default: "),a("code",[e._v("true")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("extensibleEnums")]),e._v(": Generate a fallback case class for unknown enum values (default: "),a("code",[e._v("false")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("headers")]),e._v(" (only defined for "),a("code",[e._v("url")]),e._v(" settings): Supply extra headers when fetching the schema from a URL.")]),e._v(" "),a("li",[a("code",[e._v("excludeDeprecated")]),e._v(": Exclude fields and enum values with deprecated directive (default: "),a("code",[e._v("false")]),e._v(").")])]),e._v(" "),a("h3",{attrs:{id:"manual-generation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#manual-generation"}},[e._v("#")]),e._v(" Manual generation")]),e._v(" "),a("p",[e._v("If you prefer to generate the client explicitly rather than automatically, you can use "),a("code",[e._v("calibanGenClient")]),e._v(" on the SBT CLI as follows:")]),e._v(" "),a("div",{staticClass:"language-bash extra-class"},[a("pre",{pre:!0,attrs:{class:"language-bash"}},[a("code",[e._v("calibanGenClient schemaPath outputPath "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v("--scalafmtPath path"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v("--headers name:value,name2:value2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v("--genView "),a("span",{pre:!0,attrs:{class:"token boolean"}},[e._v("true")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("|")]),e._v("false"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v("--scalarMappings gqlType:f.q.d.n.Type,gqlType2:f.q.d.n.Type2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v("--imports a.b.c._,c.d.E"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v("--splitFiles "),a("span",{pre:!0,attrs:{class:"token boolean"}},[e._v("true")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("|")]),e._v("false"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v("--enableFmt "),a("span",{pre:!0,attrs:{class:"token boolean"}},[e._v("true")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("|")]),e._v("false"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v("--extensibleEnums "),a("span",{pre:!0,attrs:{class:"token boolean"}},[e._v("true")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("|")]),e._v("false"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v("--excludeDeprecated "),a("span",{pre:!0,attrs:{class:"token boolean"}},[e._v("true")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("|")]),e._v("false"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[e._v("# example")]),e._v("\ncalibanGenClient project/schema.graphql src/main/client/Client.scala "),a("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("--genView")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[e._v("true")]),e._v(" \n")])])]),a("p",[e._v("This command will generate a Scala file in "),a("code",[e._v("outputPath")]),e._v(" containing helper functions for all the types defined in the provided GraphQL schema defined at "),a("code",[e._v("schemaPath")]),e._v(".")]),e._v(" "),a("p",[e._v("If you need to disable generating clients from "),a("code",[e._v("src/main/graphql")]),e._v(", include "),a("code",[e._v("Compile / caliban / calibanGenerator := Seq.empty")]),e._v(" in your project settings.")]),e._v(" "),a("p",[e._v("The package of the generated code is derived from the folder of "),a("code",[e._v("outputPath")]),e._v(". This can be overridden by providing an alternative package with the "),a("code",[e._v("--packageName")]),e._v(" option.\nSimilarly, the generated object name is derived from "),a("code",[e._v("outputPath")]),e._v(" file name but can be overridden with the "),a("code",[e._v("--clientName")]),e._v(" option.")]),e._v(" "),a("p",[e._v("Other options are explained above.")]),e._v(" "),a("h2",{attrs:{id:"compiletimecalibanplugin"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#compiletimecalibanplugin"}},[e._v("#")]),e._v(" CompileTimeCalibanPlugin")]),e._v(" "),a("p",[e._v("As mentioned in the introduction of the "),a("a",{attrs:{href:"#code-generation"}},[e._v("Code Generation")]),e._v(' chapter, this "meta" plugin is actually made of two "concrete" sbt plugins, '),a("code",[e._v("CompileTimeCalibanServerPlugin")]),e._v(" and "),a("code",[e._v("CompileTimeCalibanClientPlugin")]),e._v(",\nthat you'll both need to configure in your project be able to generate your Caliban client code from your Caliban server code..")]),e._v(" "),a("p",[e._v("You can find a demo project using this plugin here: "),a("a",{attrs:{href:"https://github.com/guizmaii/poc_compile_time_caliban_client_generation",target:"_blank",rel:"noopener noreferrer"}},[e._v("Demo project"),a("OutboundLink")],1)]),e._v(" "),a("p",[e._v("To generate the Caliban client code from you Caliban server code, you need to do two things:")]),e._v(" "),a("ol",[a("li",[a("p",[e._v("Tell to the plugin where your Caliban "),a("code",[e._v("GraphQL[R]")]),e._v(" instances for which you want to generate a client are and configure the client code generator."),a("br"),e._v("\nHow to configure this is explained in the following "),a("a",{attrs:{href:"#server-side-configuration"}},[e._v("Server side configuration")]),e._v(" chapter.")])]),e._v(" "),a("li",[a("p",[e._v("Tell to the plugin where you want to generate your client(s)."),a("br"),e._v("\nHow to configure this is explained in the following "),a("a",{attrs:{href:"#client-side-configuration"}},[e._v("Client side configuration")]),e._v(" chapter.")])])]),e._v(" "),a("h3",{attrs:{id:"server-side-configuration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#server-side-configuration"}},[e._v("#")]),e._v(" Server side configuration")]),e._v(" "),a("p",[e._v("First, you'll need to activate the "),a("code",[e._v("CompileTimeCalibanServerPlugin")]),e._v(" plugin in all the sbt modules of your project containing a "),a("code",[e._v("GraphQL[R]")]),e._v(" instance for which you want to generate a client.")]),e._v(" "),a("p",[e._v("Let's say you have an "),a("code",[e._v("api")]),e._v(" sbt module defined in your "),a("code",[e._v("build.sbt")]),e._v(" which contains your Caliban server code:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("lazy")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("val")]),e._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("\n project\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("enablePlugins"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("CompileTimeCalibanServerPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("p",[e._v('Now, you need to tell to the "server side" plugin where is your '),a("code",[e._v("GraphQL[R]")]),e._v(" instance for which you want to generate a client."),a("br"),e._v("\nThis "),a("code",[e._v("GraphQL[R]")]),e._v(" instance need to be "),a("code",[e._v("public")]),e._v(". If it's "),a("code",[e._v("private")]),e._v(" or "),a("code",[e._v("protected")]),e._v(", the plugin code generator will not have access to it and will fail.")]),e._v(" "),a("p",[e._v("Let's say you have an object "),a("code",[e._v("CalibanServer")]),e._v(" object in your "),a("code",[e._v("api")]),e._v(" sbt module:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("package")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[e._v("com"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("example"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("my"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("awesome"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("project"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("api")]),e._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("import")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[e._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")])]),e._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("object")]),e._v(" CalibanServer "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("{")]),e._v("\n \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("val")]),e._v(" graphqlApi"),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v(":")]),e._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("Resolvers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("resolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n \n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("}")]),e._v("\n")])])]),a("p",[e._v("You'll need to add in your sbt definition:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("lazy")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("val")]),e._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("\n project\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("enablePlugins"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("CompileTimeCalibanServerPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("settings"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" ctCalibanServer "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" ctCalibanServerSettings "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v(":")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("\n Seq"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"com.example.my.awesome.project.api.CalibanServer.graphqlApi"')]),e._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("->")]),e._v(" ClientGenerationSettings"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("default\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("p",[e._v('This is the minimal working configuration for the "server side".')]),e._v(" "),a("p",[e._v("Now, you may want to tweak how the client code is generated."),a("br"),e._v("\nFor that, you'll have to replace the "),a("code",[e._v("ClientGenerationSettings.default")]),e._v(" with the configuration that suits you the best."),a("br"),e._v("\nThis "),a("code",[e._v("ClientGenerationSettings")]),e._v(" case class gives you the following configuration options:")]),e._v(" "),a("ul",[a("li",[a("code",[e._v("packageName")]),e._v(": The package in which the code will be generated (default: "),a("code",[e._v("generated")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("clientName")]),e._v(": The name of the client class generated (default: "),a("code",[e._v("Client")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("scalafmtPath")]),e._v(": Path to a scalafmt config file (default: "),a("code",[e._v(".scalafmt.conf")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("genView")]),e._v(": If true, will generate a case class and helper method to select all fields on an object (default: "),a("code",[e._v("false")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("scalarMappings")]),e._v(": A mapping from GraphQL scalar types to JVM types, as unknown scalar types are represented as "),a("code",[e._v("String")]),e._v(" by default.")]),e._v(" "),a("li",[a("code",[e._v("imports")]),e._v(": A list of imports to be added at the top of the generated code.")]),e._v(" "),a("li",[a("code",[e._v("splitFiles")]),e._v(": Whether to split the generated code into multiple files (default: "),a("code",[e._v("false")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("enableFmt")]),e._v(": Enable code formatting with scalafmt (default: "),a("code",[e._v("true")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("extensibleEnums")]),e._v(": Generate a fallback case class for unknown enum values (default: "),a("code",[e._v("false")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("excludeDeprecated")]),e._v(": Exclude fields or enum values with deprecated directive (default: "),a("code",[e._v("false")]),e._v(").")])]),e._v(" "),a("p",[e._v("Let's take an example:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("lazy")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("val")]),e._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("\n project\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("enablePlugins"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("CompileTimeCalibanServerPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("settings"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" ctCalibanServer "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" ctCalibanServerSettings "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v(":")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("\n Seq"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"com.example.my.awesome.project.api.CalibanServer.graphqlApi"')]),e._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("->")]),e._v("\n ClientGenerationSettings"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n packageName "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"com.example.my.awesome.project.client.generated"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v("\n clientName "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"CalibanClient"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v("\n splitFiles "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[e._v("true")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("p",[e._v('That\'s all. You now know how to configure the "server side" of this plugin.'),a("br"),e._v('\nLet\'s now see how to configure the "client side".')]),e._v(" "),a("h3",{attrs:{id:"client-side-configuration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#client-side-configuration"}},[e._v("#")]),e._v(" Client side configuration")]),e._v(" "),a("p",[e._v('The "client side" of this plugin is here to help you define where your Caliban client code is generated.')]),e._v(" "),a("p",[e._v("The first thing to do is to activate the "),a("code",[e._v("CompileTimeCalibanClientPlugin")]),e._v(" in the sbt module where you want your Caliban client code to be generated into.")]),e._v(" "),a("p",[e._v("Let's say you have a "),a("code",[e._v("client")]),e._v(" sbt module defined in your "),a("code",[e._v("build.sbt")]),e._v(":")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("lazy")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("val")]),e._v(" client "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("\n project\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("enablePlugins"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("CompileTimeCalibanClientPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("p",[e._v("You only have one thing left to do."),a("br"),e._v('\nYou need to reference your "server side" sbt module (here '),a("code",[e._v("api")]),e._v(') in your "client side" sbt module (here '),a("code",[e._v("client")]),e._v(") definition so the plugin knows that you want to generate the Caliban client code for your "),a("code",[e._v("api")]),e._v(" server\nin this "),a("code",[e._v("client")]),e._v(" sbt module:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("lazy")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("val")]),e._v(" client "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("\n project\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("enablePlugins"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("CompileTimeCalibanClientPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("settings"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" ctCalibanClient "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" ctCalibanClientsSettings "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v(":")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" Seq"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("p",[e._v('This is the minimal working configuration for the "client side".')]),e._v(" "),a("p",[e._v("By default, the Caliban client code will be generated in your "),a("code",[e._v("src/main/scala")]),e._v(" directory of your "),a("code",[e._v("client")]),e._v(" sbt module."),a("br"),e._v("\nYou may prefer it not to be generated inside your - usually versioned-in-git - module code.\nFor that, the plugin provides an option to generate the code in the "),a("code",[e._v("target")]),e._v(" directory instead:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("lazy")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("val")]),e._v(" client "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("\n project\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("enablePlugins"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("CompileTimeCalibanClientPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("settings"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" ctCalibanClient "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" ctCalibanClientsSettings "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v(":")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" Seq"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v("\n Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" ctCalibanClient "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" ctCalibanClientsVersionedCode "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v(":")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[e._v("false")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[e._v("// By default, it's true.")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("p",[e._v("You're done. 🎉"),a("br"),e._v("\nYou can now reload your sbt config and recompile your project. Your Caliban client code will be generated during the compilation process.")]),e._v(" "),a("h3",{attrs:{id:"additional-information-about-compiletimecalibanplugin"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#additional-information-about-compiletimecalibanplugin"}},[e._v("#")]),e._v(" Additional information about CompileTimeCalibanPlugin")]),e._v(" "),a("p",[e._v("As you may have seen in the "),a("a",{attrs:{href:"https://github.com/guizmaii/poc_compile_time_caliban_client_generation",target:"_blank",rel:"noopener noreferrer"}},[e._v("demo project"),a("OutboundLink")],1),e._v(", you can have more complex configurations for this plugin."),a("br"),e._v("\nYou can have more than one "),a("code",[e._v("GraphQL[R]")]),e._v(" instance per server. Each "),a("code",[e._v("GraphQL[R]")]),e._v(" instance can have its own client code generation configuration."),a("br"),e._v('\nYou can also have multiple "servers" referenced in your "client" module. The plugin will generate all the clients for all the "servers" referenced in your sbt definition.')])])}),[],!1,null,null,null);a.default=s.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[26],{308:function(e,a,t){"use strict";t.r(a);var n=t(14),s=Object(n.a)({},(function(){var e=this,a=e._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[a("h1",{attrs:{id:"code-generation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#code-generation"}},[e._v("#")]),e._v(" Code Generation")]),e._v(" "),a("p",[e._v("Caliban provides two sbt plugins to generate your client(s) code.")]),e._v(" "),a("p",[e._v("The first one, named "),a("code",[e._v("CalibanPlugin")]),e._v(", allows you to generate the client code from a schema file or from a server URL, manually or automatically.")]),e._v(" "),a("p",[e._v("The second one, named "),a("code",[e._v("CompileTimeCalibanPlugin")]),e._v(', allows you to generate the client code from your server code.\nThis second "meta" plugin is actually made of two "concrete" plugins, '),a("code",[e._v("CompileTimeCalibanServerPlugin")]),e._v(" and "),a("code",[e._v("CompileTimeCalibanClientPlugin")]),e._v(", that you'll\nboth need to configure in your project to be able to generate you Caliban client code from your Caliban server code.")]),e._v(" "),a("p",[e._v("To use any of these two plugins, you'll first need to add following dependency to your "),a("code",[e._v("project/plugins.sbt")]),e._v(" file:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[e._v("addSbtPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"com.github.ghostdogpr"')]),e._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("%")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"caliban-codegen-sbt"')]),e._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("%")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"2.9.0"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("h2",{attrs:{id:"calibanplugin"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#calibanplugin"}},[e._v("#")]),e._v(" CalibanPlugin")]),e._v(" "),a("p",[e._v("The first step for building GraphQL queries with "),a("code",[e._v("caliban-client")]),e._v(" is to generate boilerplate code from a GraphQL schema. For that, you need a file containing your schema (if your backend uses "),a("code",[e._v("caliban")]),e._v(", you can get it by calling "),a("code",[e._v("GraphQL#render")]),e._v(" on your API).")]),e._v(" "),a("p",[e._v("And enable it in your "),a("code",[e._v("build.sbt")]),e._v(" file:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[e._v("enablePlugins"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("CalibanPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("h3",{attrs:{id:"from-a-schema-file"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#from-a-schema-file"}},[e._v("#")]),e._v(" From a schema file")]),e._v(" "),a("p",[e._v("At this point, the "),a("code",[e._v("caliban")]),e._v(" command will cause any files in "),a("code",[e._v("src/main/graphql")]),e._v(" to be translated into a Caliban-generated client library. This happens automatically any time you "),a("code",[e._v("compile")]),e._v(".")]),e._v(" "),a("p",[e._v("By default, all clients are generated with the same client name as the source file, in the "),a("code",[e._v("caliban")]),e._v(" top-level package.")]),e._v(" "),a("p",[e._v("In order to supply more configuration options to the code generator, you can use the "),a("code",[e._v("calibanSettings")]),e._v(" sbt setting, combined with the "),a("code",[e._v("calibanSetting")]),e._v(" function to scope the settings to a particular file:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[e._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[e._v('// The `file("Service.graphql")` is a path suffix for some file in `src/main/graphql`')]),e._v("\n Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" caliban "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" calibanSettings "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("+=")]),e._v(" calibanSetting"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"Service.graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n cs "),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("=>")]),e._v("\n cs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("packageName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"com.example.graphql.client"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("scalarMapping"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"LanguageCode"')]),e._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("->")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"com.example.models.LanguageCode"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("scalarMapping"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"Timestamp"')]),e._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("->")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"java.sql.Timestamp"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"DayOfWeek"')]),e._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("->")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"java.time.DayOfWeek"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"IntRange"')]),e._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("->")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"com.github.tminglei.slickpg.Range[Int]"')]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("imports"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"com.example.graphql.client.implicits._"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("p",[e._v("The path where the generator will look for schemas can be customized by overriding the "),a("code",[e._v("calibanSources")]),e._v(" settings:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[e._v("Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" caliban "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" calibanSources "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v(":")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"caliban"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("p",[e._v("If you want to cherry-pick certain files yourself, you can override that as well with an explicit "),a("code",[e._v("caliban / sources")]),e._v(" entry:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[e._v("Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" caliban "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" sources "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v(":")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"caliban"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"Service.graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("p",[e._v("For every entry in "),a("code",[e._v("calibanSettings")]),e._v(" for the same file, a separate client (or "),a("RouterLink",{attrs:{to:"/docs/schema.html#code-generation"}},[e._v("schema")]),e._v(", depending on the entry's "),a("code",[e._v("genType")]),e._v(" value) will be generated.")],1),e._v(" "),a("h3",{attrs:{id:"from-a-server-url"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#from-a-server-url"}},[e._v("#")]),e._v(" From a server URL")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("calibanSetting")]),e._v(" function also permits generating clients for supplied "),a("code",[e._v("url")]),e._v("'s:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[e._v(" Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" caliban "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" calibanSettings "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("+=")]),e._v(" calibanSetting"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("url"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"http://my-example-service/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n cs "),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("=>")]),e._v("\n cs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("clientName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"ExampleServiceClient"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("packageName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"com.example.graphql.client"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("h3",{attrs:{id:"generation-settings"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#generation-settings"}},[e._v("#")]),e._v(" Generation settings")]),e._v(" "),a("p",[e._v("The settings available on the "),a("code",[e._v("cs")]),e._v(" ("),a("code",[e._v("CalibanSettings")]),e._v(") builder are:")]),e._v(" "),a("ul",[a("li",[a("code",[e._v("packageName")]),e._v(": The package in which the code will be generated (default: "),a("code",[e._v("caliban")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("scalafmtPath")]),e._v(": Path to a scalafmt config file (default: "),a("code",[e._v(".scalafmt.conf")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("genView")]),e._v(": If true, will generate a case class and helper method to select all fields on an object (default: "),a("code",[e._v("false")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("scalarMappings")]),e._v(": A mapping from GraphQL scalar types to JVM types, as unknown scalar types are represented as "),a("code",[e._v("String")]),e._v(" by default.")]),e._v(" "),a("li",[a("code",[e._v("imports")]),e._v(": A list of imports to be added at the top of the generated code.")]),e._v(" "),a("li",[a("code",[e._v("splitFiles")]),e._v(": Whether to split the generated code into multiple files (default: "),a("code",[e._v("false")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("enableFmt")]),e._v(": Enable code formatting with scalafmt (default: "),a("code",[e._v("true")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("extensibleEnums")]),e._v(": Generate a fallback case class for unknown enum values (default: "),a("code",[e._v("false")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("headers")]),e._v(" (only defined for "),a("code",[e._v("url")]),e._v(" settings): Supply extra headers when fetching the schema from a URL.")]),e._v(" "),a("li",[a("code",[e._v("excludeDeprecated")]),e._v(": Exclude fields and enum values with deprecated directive (default: "),a("code",[e._v("false")]),e._v(").")])]),e._v(" "),a("h3",{attrs:{id:"manual-generation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#manual-generation"}},[e._v("#")]),e._v(" Manual generation")]),e._v(" "),a("p",[e._v("If you prefer to generate the client explicitly rather than automatically, you can use "),a("code",[e._v("calibanGenClient")]),e._v(" on the SBT CLI as follows:")]),e._v(" "),a("div",{staticClass:"language-bash extra-class"},[a("pre",{pre:!0,attrs:{class:"language-bash"}},[a("code",[e._v("calibanGenClient schemaPath outputPath "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v("--scalafmtPath path"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v("--headers name:value,name2:value2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v("--genView "),a("span",{pre:!0,attrs:{class:"token boolean"}},[e._v("true")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("|")]),e._v("false"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v("--scalarMappings gqlType:f.q.d.n.Type,gqlType2:f.q.d.n.Type2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v("--imports a.b.c._,c.d.E"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v("--splitFiles "),a("span",{pre:!0,attrs:{class:"token boolean"}},[e._v("true")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("|")]),e._v("false"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v("--enableFmt "),a("span",{pre:!0,attrs:{class:"token boolean"}},[e._v("true")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("|")]),e._v("false"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v("--extensibleEnums "),a("span",{pre:!0,attrs:{class:"token boolean"}},[e._v("true")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("|")]),e._v("false"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v("--excludeDeprecated "),a("span",{pre:!0,attrs:{class:"token boolean"}},[e._v("true")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("|")]),e._v("false"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[e._v("# example")]),e._v("\ncalibanGenClient project/schema.graphql src/main/client/Client.scala "),a("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("--genView")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[e._v("true")]),e._v(" \n")])])]),a("p",[e._v("This command will generate a Scala file in "),a("code",[e._v("outputPath")]),e._v(" containing helper functions for all the types defined in the provided GraphQL schema defined at "),a("code",[e._v("schemaPath")]),e._v(".")]),e._v(" "),a("p",[e._v("If you need to disable generating clients from "),a("code",[e._v("src/main/graphql")]),e._v(", include "),a("code",[e._v("Compile / caliban / calibanGenerator := Seq.empty")]),e._v(" in your project settings.")]),e._v(" "),a("p",[e._v("The package of the generated code is derived from the folder of "),a("code",[e._v("outputPath")]),e._v(". This can be overridden by providing an alternative package with the "),a("code",[e._v("--packageName")]),e._v(" option.\nSimilarly, the generated object name is derived from "),a("code",[e._v("outputPath")]),e._v(" file name but can be overridden with the "),a("code",[e._v("--clientName")]),e._v(" option.")]),e._v(" "),a("p",[e._v("Other options are explained above.")]),e._v(" "),a("h2",{attrs:{id:"compiletimecalibanplugin"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#compiletimecalibanplugin"}},[e._v("#")]),e._v(" CompileTimeCalibanPlugin")]),e._v(" "),a("p",[e._v("As mentioned in the introduction of the "),a("a",{attrs:{href:"#code-generation"}},[e._v("Code Generation")]),e._v(' chapter, this "meta" plugin is actually made of two "concrete" sbt plugins, '),a("code",[e._v("CompileTimeCalibanServerPlugin")]),e._v(" and "),a("code",[e._v("CompileTimeCalibanClientPlugin")]),e._v(",\nthat you'll both need to configure in your project be able to generate your Caliban client code from your Caliban server code..")]),e._v(" "),a("p",[e._v("You can find a demo project using this plugin here: "),a("a",{attrs:{href:"https://github.com/guizmaii/poc_compile_time_caliban_client_generation",target:"_blank",rel:"noopener noreferrer"}},[e._v("Demo project"),a("OutboundLink")],1)]),e._v(" "),a("p",[e._v("To generate the Caliban client code from you Caliban server code, you need to do two things:")]),e._v(" "),a("ol",[a("li",[a("p",[e._v("Tell to the plugin where your Caliban "),a("code",[e._v("GraphQL[R]")]),e._v(" instances for which you want to generate a client are and configure the client code generator."),a("br"),e._v("\nHow to configure this is explained in the following "),a("a",{attrs:{href:"#server-side-configuration"}},[e._v("Server side configuration")]),e._v(" chapter.")])]),e._v(" "),a("li",[a("p",[e._v("Tell to the plugin where you want to generate your client(s)."),a("br"),e._v("\nHow to configure this is explained in the following "),a("a",{attrs:{href:"#client-side-configuration"}},[e._v("Client side configuration")]),e._v(" chapter.")])])]),e._v(" "),a("h3",{attrs:{id:"server-side-configuration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#server-side-configuration"}},[e._v("#")]),e._v(" Server side configuration")]),e._v(" "),a("p",[e._v("First, you'll need to activate the "),a("code",[e._v("CompileTimeCalibanServerPlugin")]),e._v(" plugin in all the sbt modules of your project containing a "),a("code",[e._v("GraphQL[R]")]),e._v(" instance for which you want to generate a client.")]),e._v(" "),a("p",[e._v("Let's say you have an "),a("code",[e._v("api")]),e._v(" sbt module defined in your "),a("code",[e._v("build.sbt")]),e._v(" which contains your Caliban server code:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("lazy")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("val")]),e._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("\n project\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("enablePlugins"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("CompileTimeCalibanServerPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("p",[e._v('Now, you need to tell to the "server side" plugin where is your '),a("code",[e._v("GraphQL[R]")]),e._v(" instance for which you want to generate a client."),a("br"),e._v("\nThis "),a("code",[e._v("GraphQL[R]")]),e._v(" instance need to be "),a("code",[e._v("public")]),e._v(". If it's "),a("code",[e._v("private")]),e._v(" or "),a("code",[e._v("protected")]),e._v(", the plugin code generator will not have access to it and will fail.")]),e._v(" "),a("p",[e._v("Let's say you have an object "),a("code",[e._v("CalibanServer")]),e._v(" object in your "),a("code",[e._v("api")]),e._v(" sbt module:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("package")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[e._v("com"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("example"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("my"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("awesome"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("project"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("api")]),e._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("import")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[e._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")])]),e._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("object")]),e._v(" CalibanServer "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("{")]),e._v("\n \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("val")]),e._v(" graphqlApi"),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v(":")]),e._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),e._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("Resolvers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("resolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n \n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("}")]),e._v("\n")])])]),a("p",[e._v("You'll need to add in your sbt definition:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("lazy")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("val")]),e._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("\n project\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("enablePlugins"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("CompileTimeCalibanServerPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("settings"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" ctCalibanServer "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" ctCalibanServerSettings "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v(":")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("\n Seq"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"com.example.my.awesome.project.api.CalibanServer.graphqlApi"')]),e._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("->")]),e._v(" ClientGenerationSettings"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("default\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("p",[e._v('This is the minimal working configuration for the "server side".')]),e._v(" "),a("p",[e._v("Now, you may want to tweak how the client code is generated."),a("br"),e._v("\nFor that, you'll have to replace the "),a("code",[e._v("ClientGenerationSettings.default")]),e._v(" with the configuration that suits you the best."),a("br"),e._v("\nThis "),a("code",[e._v("ClientGenerationSettings")]),e._v(" case class gives you the following configuration options:")]),e._v(" "),a("ul",[a("li",[a("code",[e._v("packageName")]),e._v(": The package in which the code will be generated (default: "),a("code",[e._v("generated")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("clientName")]),e._v(": The name of the client class generated (default: "),a("code",[e._v("Client")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("scalafmtPath")]),e._v(": Path to a scalafmt config file (default: "),a("code",[e._v(".scalafmt.conf")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("genView")]),e._v(": If true, will generate a case class and helper method to select all fields on an object (default: "),a("code",[e._v("false")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("scalarMappings")]),e._v(": A mapping from GraphQL scalar types to JVM types, as unknown scalar types are represented as "),a("code",[e._v("String")]),e._v(" by default.")]),e._v(" "),a("li",[a("code",[e._v("imports")]),e._v(": A list of imports to be added at the top of the generated code.")]),e._v(" "),a("li",[a("code",[e._v("splitFiles")]),e._v(": Whether to split the generated code into multiple files (default: "),a("code",[e._v("false")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("enableFmt")]),e._v(": Enable code formatting with scalafmt (default: "),a("code",[e._v("true")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("extensibleEnums")]),e._v(": Generate a fallback case class for unknown enum values (default: "),a("code",[e._v("false")]),e._v(").")]),e._v(" "),a("li",[a("code",[e._v("excludeDeprecated")]),e._v(": Exclude fields or enum values with deprecated directive (default: "),a("code",[e._v("false")]),e._v(").")])]),e._v(" "),a("p",[e._v("Let's take an example:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("lazy")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("val")]),e._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("\n project\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("enablePlugins"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("CompileTimeCalibanServerPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("settings"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" ctCalibanServer "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" ctCalibanServerSettings "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v(":")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("\n Seq"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"com.example.my.awesome.project.api.CalibanServer.graphqlApi"')]),e._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("->")]),e._v("\n ClientGenerationSettings"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n packageName "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"com.example.my.awesome.project.client.generated"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v("\n clientName "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"CalibanClient"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v("\n splitFiles "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[e._v("true")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("p",[e._v('That\'s all. You now know how to configure the "server side" of this plugin.'),a("br"),e._v('\nLet\'s now see how to configure the "client side".')]),e._v(" "),a("h3",{attrs:{id:"client-side-configuration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#client-side-configuration"}},[e._v("#")]),e._v(" Client side configuration")]),e._v(" "),a("p",[e._v('The "client side" of this plugin is here to help you define where your Caliban client code is generated.')]),e._v(" "),a("p",[e._v("The first thing to do is to activate the "),a("code",[e._v("CompileTimeCalibanClientPlugin")]),e._v(" in the sbt module where you want your Caliban client code to be generated into.")]),e._v(" "),a("p",[e._v("Let's say you have a "),a("code",[e._v("client")]),e._v(" sbt module defined in your "),a("code",[e._v("build.sbt")]),e._v(":")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("lazy")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("val")]),e._v(" client "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("\n project\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("enablePlugins"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("CompileTimeCalibanClientPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("p",[e._v("You only have one thing left to do."),a("br"),e._v('\nYou need to reference your "server side" sbt module (here '),a("code",[e._v("api")]),e._v(') in your "client side" sbt module (here '),a("code",[e._v("client")]),e._v(") definition so the plugin knows that you want to generate the Caliban client code for your "),a("code",[e._v("api")]),e._v(" server\nin this "),a("code",[e._v("client")]),e._v(" sbt module:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("lazy")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("val")]),e._v(" client "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("\n project\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("enablePlugins"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("CompileTimeCalibanClientPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("settings"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" ctCalibanClient "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" ctCalibanClientsSettings "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v(":")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" Seq"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("p",[e._v('This is the minimal working configuration for the "client side".')]),e._v(" "),a("p",[e._v("By default, the Caliban client code will be generated in your "),a("code",[e._v("src/main/scala")]),e._v(" directory of your "),a("code",[e._v("client")]),e._v(" sbt module."),a("br"),e._v("\nYou may prefer it not to be generated inside your - usually versioned-in-git - module code.\nFor that, the plugin provides an option to generate the code in the "),a("code",[e._v("target")]),e._v(" directory instead:")]),e._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("lazy")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[e._v("val")]),e._v(" client "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("\n project\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("enablePlugins"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("CompileTimeCalibanClientPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("settings"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("\n Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" ctCalibanClient "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" ctCalibanClientsSettings "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v(":")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" Seq"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v("\n Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" ctCalibanClient "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("/")]),e._v(" ctCalibanClientsVersionedCode "),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v(":")]),a("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[e._v("false")]),e._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[e._v("// By default, it's true.")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),a("p",[e._v("You're done. 🎉"),a("br"),e._v("\nYou can now reload your sbt config and recompile your project. Your Caliban client code will be generated during the compilation process.")]),e._v(" "),a("h3",{attrs:{id:"additional-information-about-compiletimecalibanplugin"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#additional-information-about-compiletimecalibanplugin"}},[e._v("#")]),e._v(" Additional information about CompileTimeCalibanPlugin")]),e._v(" "),a("p",[e._v("As you may have seen in the "),a("a",{attrs:{href:"https://github.com/guizmaii/poc_compile_time_caliban_client_generation",target:"_blank",rel:"noopener noreferrer"}},[e._v("demo project"),a("OutboundLink")],1),e._v(", you can have more complex configurations for this plugin."),a("br"),e._v("\nYou can have more than one "),a("code",[e._v("GraphQL[R]")]),e._v(" instance per server. Each "),a("code",[e._v("GraphQL[R]")]),e._v(" instance can have its own client code generation configuration."),a("br"),e._v('\nYou can also have multiple "servers" referenced in your "client" module. The plugin will generate all the clients for all the "servers" referenced in your sbt definition.')])])}),[],!1,null,null,null);a.default=s.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/27.28800ed0.js b/docs/assets/js/27.93ecdab2.js similarity index 99% rename from docs/assets/js/27.28800ed0.js rename to docs/assets/js/27.93ecdab2.js index 624e28a0ea..d92b1733a5 100644 --- a/docs/assets/js/27.28800ed0.js +++ b/docs/assets/js/27.93ecdab2.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[27],{308:function(t,a,s){"use strict";s.r(a);var e=s(14),n=Object(e.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"getting-started"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#getting-started"}},[t._v("#")]),t._v(" Getting Started")]),t._v(" "),a("p",[a("strong",[t._v("Caliban Client")]),t._v(" is a module independent from Caliban Server that makes it possible to write GraphQL queries using Scala code in a type-safe and functional fashion. It is built on top of "),a("a",{attrs:{href:"https://github.com/softwaremill/sttp",target:"_blank",rel:"noopener noreferrer"}},[t._v("sttp"),a("OutboundLink")],1),t._v(", which means you can run requests using the backend of your choice.")]),t._v(" "),a("p",[t._v("Just like the server module, Caliban Client offers a purely functional interface and keeps the boilerplate minimal. It works as follows:")]),t._v(" "),a("ol",[a("li",[t._v("Use the "),a("code",[t._v("caliban-codegen-sbt")]),t._v(" tool to generate boilerplate code from a given GraphQL schema")]),t._v(" "),a("li",[t._v("Write your GraphQL queries/mutations by combining helpers from the generated code")]),t._v(" "),a("li",[t._v("Transform your queries/mutations into an "),a("code",[t._v("sttp")]),t._v(" request and run them with your preferred backend")])]),t._v(" "),a("h2",{attrs:{id:"dependencies"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#dependencies"}},[t._v("#")]),t._v(" Dependencies")]),t._v(" "),a("p",[t._v("To use "),a("code",[t._v("caliban-client")]),t._v(", add the following dependency to your "),a("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-client"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),t._v("\n")])])]),a("p",[t._v("Caliban-client is available for ScalaJS. To use it in a ScalaJS project, instead add this dependency to your "),a("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-client"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),t._v("\n")])])]),a("h2",{attrs:{id:"code-generation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#code-generation"}},[t._v("#")]),t._v(" Code generation")]),t._v(" "),a("p",[t._v("Caliban provides several ways to generate the boilerplate code. To get started, we are going to generate it by running a\nsimple sbt command, but you can look at the "),a("RouterLink",{attrs:{to:"/docs/client-codegen.html"}},[t._v("Code generation")]),t._v(" page for more options.")],1),t._v(" "),a("p",[t._v("You'll first need to add following dependency to your "),a("code",[t._v("project/plugins.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("addSbtPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-codegen-sbt"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("And to enable the plugin in your "),a("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("enablePlugins"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CalibanPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("Then, you can run the following command in your sbt.")]),t._v(" "),a("div",{staticClass:"language-bash extra-class"},[a("pre",{pre:!0,attrs:{class:"language-bash"}},[a("code",[t._v("calibanGenClient schemaPath outputPath\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# example")]),t._v("\ncalibanGenClient project/schema.graphql src/main/client/Client.scala\n")])])]),a("p",[a("code",[t._v("schemaPath")]),t._v(" is the path to a GraphQL schema file (if your backend uses "),a("code",[t._v("caliban")]),t._v(", you can get it by calling "),a("code",[t._v("GraphQL#render")]),t._v(" on your API).\nInstead of a file, you can provide a URL and the schema will be obtained using introspection.")]),t._v(" "),a("p",[a("code",[t._v("outputPath")]),t._v(" is the path where the generated code will be written. The folder needs to exist.")]),t._v(" "),a("p",[t._v("This command will generate a Scala file in "),a("code",[t._v("outputPath")]),t._v(" containing helper functions for all the types defined in the provided GraphQL schema defined at "),a("code",[t._v("schemaPath")]),t._v(".")]),t._v(" "),a("h2",{attrs:{id:"query-building"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#query-building"}},[t._v("#")]),t._v(" Query building")]),t._v(" "),a("p",[t._v("Once the boilerplate code is generated, you can start building queries. For each "),a("em",[t._v("type")]),t._v(" in your schema, a corresponding Scala object has been created. For each "),a("em",[t._v("field")]),t._v(" in your schema, a corresponding Scala function has been created.")]),t._v(" "),a("p",[t._v("For example, given the following schema:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("nicknames")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("origin")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Your generated code will have the following:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Character "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" nicknames"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" origin"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("A "),a("code",[t._v("SelectionBuilder[Origin, A]")]),t._v(" is a selection from a parent type "),a("code",[t._v("Origin")]),t._v(" that returns a result of type "),a("code",[t._v("A")]),t._v(". In this example, "),a("code",[t._v("name")]),t._v(" is a selection from a "),a("code",[t._v("Character")]),t._v(" that returns a "),a("code",[t._v("String")]),t._v(".")]),t._v(" "),a("p",[t._v("You can combine multiple selections using the "),a("code",[t._v("~")]),t._v(" operator. The new result type will be a tuple from the 2 combined result types. Note that you can only combine selections that have the same origin.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" selection"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nicknames\n")])])]),a("p",[t._v("If you combine multiple fields, it is more convenient to have a case class to represent your data (to avoid seeing nested tuples). You can use "),a("code",[t._v("mapN")]),t._v(" to map a nested tuple to a case class.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" CharacterView"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" nickname"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" origin"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" character"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CharacterView"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nicknames "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mapN"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CharacterView"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("Fields that return an object type will require an inner selection, which is another "),a("code",[t._v("SelectionBuilder")]),t._v(". Let's consider the following "),a("code",[t._v("Query")]),t._v(" type.")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Query")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("characters")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("When calling "),a("code",[t._v("characters")]),t._v(", we need to provide a "),a("code",[t._v("SelectionBuilder[Character, ?]")]),t._v(" to indicate which fields to select on the returned "),a("code",[t._v("Character")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" query"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("RootQuery"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterView"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characters "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nicknames "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mapN"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CharacterView"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Or if we reuse the "),a("code",[t._v("character")]),t._v(" selection we just created:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" query"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("RootQuery"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterView"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characters "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n character\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Because this is Scala code, you can easily reuse a selection in multiple places without having to worry about GraphQL fragments. The Scala compiler will also make sure that you only combine fields that make sense.")]),t._v(" "),a("p",[t._v("When a field requires an argument, the helper method for the field will require one as well. Let's enrich our query:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Query")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("characters")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("origin")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("You now need to provide an "),a("code",[t._v("Origin")]),t._v(" when calling "),a("code",[t._v("characters")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" query"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("RootQuery"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterView"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("MARS"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n character\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"request-execution"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-execution"}},[t._v("#")]),t._v(" Request execution")]),t._v(" "),a("p",[t._v("Once your query or mutation is created, it is time to execute it. To do that, you can transform your "),a("code",[t._v("SelectionBuilder")]),t._v(" into an "),a("code",[t._v("sttp")]),t._v(" request by calling "),a("code",[t._v(".toRequest")]),t._v(".")]),t._v(" "),a("p",[t._v("This function takes the URL of your GraphQL server and some options:")]),t._v(" "),a("ul",[a("li",[t._v("a boolean "),a("code",[t._v("useVariables")]),t._v(" that determines if arguments should be using variables or not (default: false)")]),t._v(" "),a("li",[t._v("an optional string "),a("code",[t._v("queryName")]),t._v(" if you want to name your query (default: no name)")]),t._v(" "),a("li",[t._v("a boolean "),a("code",[t._v("dropNullInputValues")]),t._v(" that determines if null fields from input objects should be dropped (default: false)")])]),t._v(" "),a("p",[t._v("You can then simply run the "),a("code",[t._v("sttp")]),t._v(" request with the backend of your choice. See the "),a("a",{attrs:{href:"https://sttp.readthedocs.io/en/latest/",target:"_blank",rel:"noopener noreferrer"}},[t._v("sttp docs"),a("OutboundLink")],1),t._v(" if you are not familiar with it.")]),t._v(" "),a("p",[t._v("Here is an example using the "),a("code",[t._v("AsyncHttpClient")]),t._v(" backend for "),a("code",[t._v("ZIO")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("client3"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("client3"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("asynchttpclient"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("AsyncHttpClientZioBackend\n\nAsyncHttpClientZioBackend"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("flatMap "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" backend "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" serverUrl "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("uri")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://localhost:8088/api/graphql"')])]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" result"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterView"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toRequest"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("serverUrl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("send"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("body"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("absolve\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("As a result, we get a ZIO "),a("code",[t._v("Task")]),t._v(" whose return type is the same as our "),a("code",[t._v("SelectionBuilder")]),t._v(". The sttp request does not only contain the request to send, but also takes care of parsing the response into the expected type.")]),t._v(" "),a("p",[t._v("The "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/",target:"_blank",rel:"noopener noreferrer"}},[t._v("examples"),a("OutboundLink")],1),t._v(" project contains a runnable sample code that queries the example GraphQL backend.")]),t._v(" "),a("div",{staticClass:"custom-block warning"},[a("p",{staticClass:"custom-block-title"},[t._v("Limitations")]),t._v(" "),a("p",[t._v("Only Queries and Mutations are supported as sttp requests.\nSubscriptions are supported in the laminext module, and this code can easily be adapted to other frameworks (the relevant code is only a few lines long).")]),t._v(" "),a("p",[t._v("Type extensions are not supported by the codegen tool.")])])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[27],{309:function(t,a,s){"use strict";s.r(a);var e=s(14),n=Object(e.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"getting-started"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#getting-started"}},[t._v("#")]),t._v(" Getting Started")]),t._v(" "),a("p",[a("strong",[t._v("Caliban Client")]),t._v(" is a module independent from Caliban Server that makes it possible to write GraphQL queries using Scala code in a type-safe and functional fashion. It is built on top of "),a("a",{attrs:{href:"https://github.com/softwaremill/sttp",target:"_blank",rel:"noopener noreferrer"}},[t._v("sttp"),a("OutboundLink")],1),t._v(", which means you can run requests using the backend of your choice.")]),t._v(" "),a("p",[t._v("Just like the server module, Caliban Client offers a purely functional interface and keeps the boilerplate minimal. It works as follows:")]),t._v(" "),a("ol",[a("li",[t._v("Use the "),a("code",[t._v("caliban-codegen-sbt")]),t._v(" tool to generate boilerplate code from a given GraphQL schema")]),t._v(" "),a("li",[t._v("Write your GraphQL queries/mutations by combining helpers from the generated code")]),t._v(" "),a("li",[t._v("Transform your queries/mutations into an "),a("code",[t._v("sttp")]),t._v(" request and run them with your preferred backend")])]),t._v(" "),a("h2",{attrs:{id:"dependencies"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#dependencies"}},[t._v("#")]),t._v(" Dependencies")]),t._v(" "),a("p",[t._v("To use "),a("code",[t._v("caliban-client")]),t._v(", add the following dependency to your "),a("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-client"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),t._v("\n")])])]),a("p",[t._v("Caliban-client is available for ScalaJS. To use it in a ScalaJS project, instead add this dependency to your "),a("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-client"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),t._v("\n")])])]),a("h2",{attrs:{id:"code-generation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#code-generation"}},[t._v("#")]),t._v(" Code generation")]),t._v(" "),a("p",[t._v("Caliban provides several ways to generate the boilerplate code. To get started, we are going to generate it by running a\nsimple sbt command, but you can look at the "),a("RouterLink",{attrs:{to:"/docs/client-codegen.html"}},[t._v("Code generation")]),t._v(" page for more options.")],1),t._v(" "),a("p",[t._v("You'll first need to add following dependency to your "),a("code",[t._v("project/plugins.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("addSbtPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-codegen-sbt"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("And to enable the plugin in your "),a("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("enablePlugins"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CalibanPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("Then, you can run the following command in your sbt.")]),t._v(" "),a("div",{staticClass:"language-bash extra-class"},[a("pre",{pre:!0,attrs:{class:"language-bash"}},[a("code",[t._v("calibanGenClient schemaPath outputPath\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# example")]),t._v("\ncalibanGenClient project/schema.graphql src/main/client/Client.scala\n")])])]),a("p",[a("code",[t._v("schemaPath")]),t._v(" is the path to a GraphQL schema file (if your backend uses "),a("code",[t._v("caliban")]),t._v(", you can get it by calling "),a("code",[t._v("GraphQL#render")]),t._v(" on your API).\nInstead of a file, you can provide a URL and the schema will be obtained using introspection.")]),t._v(" "),a("p",[a("code",[t._v("outputPath")]),t._v(" is the path where the generated code will be written. The folder needs to exist.")]),t._v(" "),a("p",[t._v("This command will generate a Scala file in "),a("code",[t._v("outputPath")]),t._v(" containing helper functions for all the types defined in the provided GraphQL schema defined at "),a("code",[t._v("schemaPath")]),t._v(".")]),t._v(" "),a("h2",{attrs:{id:"query-building"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#query-building"}},[t._v("#")]),t._v(" Query building")]),t._v(" "),a("p",[t._v("Once the boilerplate code is generated, you can start building queries. For each "),a("em",[t._v("type")]),t._v(" in your schema, a corresponding Scala object has been created. For each "),a("em",[t._v("field")]),t._v(" in your schema, a corresponding Scala function has been created.")]),t._v(" "),a("p",[t._v("For example, given the following schema:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("nicknames")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("origin")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Your generated code will have the following:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Character "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" nicknames"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" origin"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("A "),a("code",[t._v("SelectionBuilder[Origin, A]")]),t._v(" is a selection from a parent type "),a("code",[t._v("Origin")]),t._v(" that returns a result of type "),a("code",[t._v("A")]),t._v(". In this example, "),a("code",[t._v("name")]),t._v(" is a selection from a "),a("code",[t._v("Character")]),t._v(" that returns a "),a("code",[t._v("String")]),t._v(".")]),t._v(" "),a("p",[t._v("You can combine multiple selections using the "),a("code",[t._v("~")]),t._v(" operator. The new result type will be a tuple from the 2 combined result types. Note that you can only combine selections that have the same origin.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" selection"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nicknames\n")])])]),a("p",[t._v("If you combine multiple fields, it is more convenient to have a case class to represent your data (to avoid seeing nested tuples). You can use "),a("code",[t._v("mapN")]),t._v(" to map a nested tuple to a case class.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" CharacterView"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" nickname"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" origin"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" character"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CharacterView"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nicknames "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mapN"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CharacterView"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("Fields that return an object type will require an inner selection, which is another "),a("code",[t._v("SelectionBuilder")]),t._v(". Let's consider the following "),a("code",[t._v("Query")]),t._v(" type.")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Query")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("characters")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("When calling "),a("code",[t._v("characters")]),t._v(", we need to provide a "),a("code",[t._v("SelectionBuilder[Character, ?]")]),t._v(" to indicate which fields to select on the returned "),a("code",[t._v("Character")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" query"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("RootQuery"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterView"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characters "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nicknames "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mapN"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CharacterView"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Or if we reuse the "),a("code",[t._v("character")]),t._v(" selection we just created:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" query"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("RootQuery"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterView"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characters "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n character\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Because this is Scala code, you can easily reuse a selection in multiple places without having to worry about GraphQL fragments. The Scala compiler will also make sure that you only combine fields that make sense.")]),t._v(" "),a("p",[t._v("When a field requires an argument, the helper method for the field will require one as well. Let's enrich our query:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Query")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("characters")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("origin")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("You now need to provide an "),a("code",[t._v("Origin")]),t._v(" when calling "),a("code",[t._v("characters")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" query"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("RootQuery"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterView"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("MARS"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n character\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"request-execution"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-execution"}},[t._v("#")]),t._v(" Request execution")]),t._v(" "),a("p",[t._v("Once your query or mutation is created, it is time to execute it. To do that, you can transform your "),a("code",[t._v("SelectionBuilder")]),t._v(" into an "),a("code",[t._v("sttp")]),t._v(" request by calling "),a("code",[t._v(".toRequest")]),t._v(".")]),t._v(" "),a("p",[t._v("This function takes the URL of your GraphQL server and some options:")]),t._v(" "),a("ul",[a("li",[t._v("a boolean "),a("code",[t._v("useVariables")]),t._v(" that determines if arguments should be using variables or not (default: false)")]),t._v(" "),a("li",[t._v("an optional string "),a("code",[t._v("queryName")]),t._v(" if you want to name your query (default: no name)")]),t._v(" "),a("li",[t._v("a boolean "),a("code",[t._v("dropNullInputValues")]),t._v(" that determines if null fields from input objects should be dropped (default: false)")])]),t._v(" "),a("p",[t._v("You can then simply run the "),a("code",[t._v("sttp")]),t._v(" request with the backend of your choice. See the "),a("a",{attrs:{href:"https://sttp.readthedocs.io/en/latest/",target:"_blank",rel:"noopener noreferrer"}},[t._v("sttp docs"),a("OutboundLink")],1),t._v(" if you are not familiar with it.")]),t._v(" "),a("p",[t._v("Here is an example using the "),a("code",[t._v("AsyncHttpClient")]),t._v(" backend for "),a("code",[t._v("ZIO")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("client3"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("client3"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("asynchttpclient"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("AsyncHttpClientZioBackend\n\nAsyncHttpClientZioBackend"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("flatMap "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" backend "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" serverUrl "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("uri")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://localhost:8088/api/graphql"')])]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" result"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterView"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toRequest"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("serverUrl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("send"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("body"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("absolve\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("As a result, we get a ZIO "),a("code",[t._v("Task")]),t._v(" whose return type is the same as our "),a("code",[t._v("SelectionBuilder")]),t._v(". The sttp request does not only contain the request to send, but also takes care of parsing the response into the expected type.")]),t._v(" "),a("p",[t._v("The "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/",target:"_blank",rel:"noopener noreferrer"}},[t._v("examples"),a("OutboundLink")],1),t._v(" project contains a runnable sample code that queries the example GraphQL backend.")]),t._v(" "),a("div",{staticClass:"custom-block warning"},[a("p",{staticClass:"custom-block-title"},[t._v("Limitations")]),t._v(" "),a("p",[t._v("Only Queries and Mutations are supported as sttp requests.\nSubscriptions are supported in the laminext module, and this code can easily be adapted to other frameworks (the relevant code is only a few lines long).")]),t._v(" "),a("p",[t._v("Type extensions are not supported by the codegen tool.")])])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/29.8ad5262b.js b/docs/assets/js/29.e973475c.js similarity index 99% rename from docs/assets/js/29.8ad5262b.js rename to docs/assets/js/29.e973475c.js index c0c8a8f9a5..7733b7bbb2 100644 --- a/docs/assets/js/29.8ad5262b.js +++ b/docs/assets/js/29.e973475c.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[29],{311:function(t,a,e){"use strict";e.r(a);var s=e(14),n=Object(s.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"federation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#federation"}},[t._v("#")]),t._v(" Federation")]),t._v(" "),a("p",[a("strong",[t._v("Federation")]),t._v(" is an optional module which can be included in your configuration to enroll with a federated schema.")]),t._v(" "),a("h2",{attrs:{id:"dependencies"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#dependencies"}},[t._v("#")]),t._v(" Dependencies")]),t._v(" "),a("p",[a("code",[t._v("caliban-federation")]),t._v(" only depends on "),a("code",[t._v("caliban-core")]),t._v(" and is very unobtrusive.")]),t._v(" "),a("p",[t._v("To use, add the following dependency to your "),a("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-federation"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),t._v("\n")])])]),a("h2",{attrs:{id:"federating"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#federating"}},[t._v("#")]),t._v(" Federating")]),t._v(" "),a("p",[t._v("Federation allows graphs to become part of a larger graph without having to share models or create brittle\nschema stitching code at the gateway level.")]),t._v(" "),a("p",[t._v("You can read more about federation and why it may be useful "),a("a",{attrs:{href:"https://www.apollographql.com/docs/apollo-server/federation/introduction/",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1),t._v(".")]),t._v(" "),a("p",[t._v("Federation creates a wrapper over your existing schema so that it can add the necessary hooks to support\ninteraction with the gateway.")]),t._v(" "),a("p",[t._v("If you already have a graph you can add federation simply by adding the "),a("code",[t._v("federated")]),t._v(" annotation:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("federation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n characters "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Amos"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" federatedSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" schema @@ federated\n")])])]),a("p",[t._v("This will wrap the bare minimum schema additions around your API so that the gateway will recognize your schema.\nTo actually enable entity resolution you will need to do a bit of leg work.")]),t._v(" "),a("p",[t._v('First, any types that will be "resolvable" need to be annotated with a '),a("code",[t._v("@key")]),t._v(" directive. You can use a helper function found\nin the "),a("code",[t._v("federation")]),t._v(" package to help with that.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLKey")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("The "),a("code",[t._v('"name"')]),t._v(" field is a field selector minus the outer braces.")]),t._v(" "),a("p",[t._v("If you need to extend a type from another service, you will need to define a stub version of it in the current service\nand annotate it with the "),a("code",[t._v("@extends")]),t._v(" annotation")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLKey")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"season episode"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n"),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLExtend")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Episode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLExternal")]),t._v(" season"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLExternal")]),t._v(" episode"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cast"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("Note the additional annotations we needed in this case. "),a("code",[t._v("Extend")]),t._v(" is needed to tell the gateway that this type is defined within\nanother service, while the "),a("code",[t._v("External")]),t._v(" flags these fields as being owned by the other service (there are several other annotations\navailable that you are encouraged to read about).")]),t._v(" "),a("p",[t._v("Once you have annotated your types, you need to tell "),a("code",[t._v("Federation")]),t._v(" how to resolve those types. Federation uses a slightly\ndifferent mechanism in resolving types from a standard GraphQL query, so for each type that you wish to support, you will\nneed to add an "),a("code",[t._v("EntityResolver")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("EntityResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterService"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CharacterArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" \n ZQuery"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getCharacter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n")])])]),a("p",[a("code",[t._v("EntityResolvers")]),t._v(' like normal field resolvers also supports a "metadata" variant which can be used to inspect the requested\nfields and potentially optimize the resulting query. You can use the provided helper method if you need to access the metadata field:')]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("EntityResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromMetadata"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" args "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fields"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("forall"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" ZQuery"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Nil"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" ZQuery"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getCharacter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("In the above we need to define an resolver which takes an "),a("code",[t._v("R")]),t._v(" environment type,\nan "),a("code",[t._v("A")]),t._v(" which has an implicit "),a("code",[t._v("ArgBuilder")]),t._v(" and an "),a("code",[t._v("Option[Out]")]),t._v(" where "),a("code",[t._v("Out")]),t._v(" has an implicit\n"),a("code",[t._v("Schema[R, Out]")]),t._v(" available. Creating the above we can now add these resolvers to our federated schema like so:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("schema @@ federated"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("aResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" additionalResolvers"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("You can now use the resulting "),a("code",[t._v("GraphQL[R]")]),t._v(" to start querying. You can also see the full code example "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/federation",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1)]),t._v(" "),a("h2",{attrs:{id:"tracing"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#tracing"}},[t._v("#")]),t._v(" Tracing")]),t._v(" "),a("p",[t._v("Federated tracing is slightly different from standard apollo-tracing thus it comes with its own wrapper defined in the "),a("code",[t._v("caliban-federation")]),t._v(" module.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("federation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tracing"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ApolloFederatedTracing\n\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" schema @@ federated"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" additionalResolvers"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" _"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@ ApolloFederatedTracing"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("In federated tracing the gateway communicates with the implementing service via a header "),a("code",[t._v("apollo-federation-include-trace")]),t._v(",\nfor now the only value it can send is "),a("code",[t._v("ftv1")]),t._v(". Thus if you detect this header then you should enable tracing otherwise you can disable it.")]),t._v(" "),a("p",[t._v("If you are using one of the wrappers you are done, they will automatically detect when the gateway\nenables tracing on a request. However, if you are calling the "),a("code",[t._v("interpreter.execute")]),t._v(" independently or you have some other custom\nset up you will need to add one more step to enable tracing.")]),t._v(" "),a("p",[t._v("If you wish to enable it manually (after detecting the header with your preferred framework) you can call: "),a("code",[t._v("request.withFederatedTracing")]),t._v(" which will return a new "),a("code",[t._v("GraphQLRequest")]),t._v(" that informs the wrapper\nthat it should include tracing data as part of the response extensions.")]),t._v(" "),a("h2",{attrs:{id:"federation-v2"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#federation-v2"}},[t._v("#")]),t._v(" Federation V2")]),t._v(" "),a("p",[t._v("Caliban can support the v2 federation specification as well. If your gateway supports the "),a("a",{attrs:{href:"https://www.apollographql.com/docs/federation/federation-spec",target:"_blank",rel:"noopener noreferrer"}},[t._v("Federation V2 specification"),a("OutboundLink")],1),t._v(", you can specify the supported feature set\nby using "),a("code",[t._v("caliban.federation.v2_x")]),t._v(" where "),a("code",[t._v("x")]),t._v(" is the minor version of the specification you wish to use.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Directive")]),t._v(" "),a("th",[t._v("Caliban Type")]),t._v(" "),a("th",[t._v("Version")]),t._v(" "),a("th",[t._v("Caliban package")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("@shareable")])]),t._v(" "),a("td",[a("code",[t._v("@GQLShareable")])]),t._v(" "),a("td",[t._v("v2.0")]),t._v(" "),a("td",[a("code",[t._v("caliban.federation.v2_0")])])]),t._v(" "),a("tr",[a("td",[a("code",[t._v("@inaccessable")])]),t._v(" "),a("td",[a("code",[t._v("@GQLInaccessible")])]),t._v(" "),a("td",[t._v("v2.0")]),t._v(" "),a("td",[a("code",[t._v("caliban.federation.v2_0")])])]),t._v(" "),a("tr",[a("td",[a("code",[t._v("@override")])]),t._v(" "),a("td",[a("code",[t._v("@GQLOverride")])]),t._v(" "),a("td",[t._v("v2.0")]),t._v(" "),a("td",[a("code",[t._v("caliban.federation.v2_0")])])]),t._v(" "),a("tr",[a("td",[a("code",[t._v("@tag")])]),t._v(" "),a("td",[a("code",[t._v("@GQLTag")])]),t._v(" "),a("td",[t._v("v2.0")]),t._v(" "),a("td",[a("code",[t._v("caliban.federation.v2_0")])])]),t._v(" "),a("tr",[a("td",[a("code",[t._v("@composeDirective")])]),t._v(" "),a("td",[a("code",[t._v("ComposeDirective")])]),t._v(" "),a("td",[t._v("v2.1")]),t._v(" "),a("td",[a("code",[t._v("caliban.federation.v2_1")])])]),t._v(" "),a("tr",[a("td",[a("code",[t._v("@interfaceObject")])]),t._v(" "),a("td",[a("code",[t._v("@GQLInterfaceObject")])]),t._v(" "),a("td",[t._v("v2.3")]),t._v(" "),a("td",[a("code",[t._v("caliban.federation.v2_3")])])])])]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("GQLKey")]),t._v(" field now also supports the "),a("code",[t._v("resolvable")]),t._v(" argument.")]),t._v(" "),a("p",[t._v("Using the new "),a("code",[t._v("federated")]),t._v(" aspect from any v2_x package will automatically make your graph available as a v2 schema,\neven if you aren't using the new directives.")]),t._v(" "),a("p",[t._v("For more information see the "),a("a",{attrs:{href:"https://www.apollographql.com/docs/federation/federation-2/new-in-federation-2/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Federation V2 specification"),a("OutboundLink")],1),t._v(".")]),t._v(" "),a("h3",{attrs:{id:"customizing-federation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#customizing-federation"}},[t._v("#")]),t._v(" Customizing Federation")]),t._v(" "),a("p",[t._v("Federation 2.1 introduced a new schema level directive called "),a("code",[t._v("@composeDirective")]),t._v(" which allows you to specify custom directives that should\nbe visible to clients of the gateway (by default all directives are hidden to clients of the gateway)")]),t._v(" "),a("p",[t._v("GraphQL federation is an evolving specification and not all routers support all features.\nCaliban provides support for "),a("code",[t._v("v2.0")]),t._v(", "),a("code",[t._v("v2.1")]),t._v(" and "),a("code",[t._v("v2.3")]),t._v(" of the specification. If you need to use\nan earlier version or you need to customize some aspect of the federation directives (for instance by providing your own "),a("code",[t._v("@composeDirective")]),t._v("s) you can do so by simply extending the "),a("code",[t._v("FederationV2")]),t._v(" class.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// With a package object but you can also create a normal object")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("object")]),t._v(" myFederation "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" FederationV2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Versions"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v2_3 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("::")]),t._v(" \n Link"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https://myspecs.dev/myDirective/v1.0"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Import"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@myDirective"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Import"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@anotherDirective"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" as "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@hello"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("::")]),t._v(" \n ComposeDirective"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@myDirective"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("::")]),t._v(" \n ComposeDirective"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@hello"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("::")]),t._v(" Nil\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("with")]),t._v(" FederationDirectivesV2_3\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Then import your new federation object instead of `caliban.federation.v2_3`")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("myFederation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n")])])])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[29],{311:function(t,a,e){"use strict";e.r(a);var s=e(14),n=Object(s.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"federation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#federation"}},[t._v("#")]),t._v(" Federation")]),t._v(" "),a("p",[a("strong",[t._v("Federation")]),t._v(" is an optional module which can be included in your configuration to enroll with a federated schema.")]),t._v(" "),a("h2",{attrs:{id:"dependencies"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#dependencies"}},[t._v("#")]),t._v(" Dependencies")]),t._v(" "),a("p",[a("code",[t._v("caliban-federation")]),t._v(" only depends on "),a("code",[t._v("caliban-core")]),t._v(" and is very unobtrusive.")]),t._v(" "),a("p",[t._v("To use, add the following dependency to your "),a("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-federation"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),t._v("\n")])])]),a("h2",{attrs:{id:"federating"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#federating"}},[t._v("#")]),t._v(" Federating")]),t._v(" "),a("p",[t._v("Federation allows graphs to become part of a larger graph without having to share models or create brittle\nschema stitching code at the gateway level.")]),t._v(" "),a("p",[t._v("You can read more about federation and why it may be useful "),a("a",{attrs:{href:"https://www.apollographql.com/docs/apollo-server/federation/introduction/",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1),t._v(".")]),t._v(" "),a("p",[t._v("Federation creates a wrapper over your existing schema so that it can add the necessary hooks to support\ninteraction with the gateway.")]),t._v(" "),a("p",[t._v("If you already have a graph you can add federation simply by adding the "),a("code",[t._v("federated")]),t._v(" annotation:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("federation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n characters "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Amos"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" federatedSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" schema @@ federated\n")])])]),a("p",[t._v("This will wrap the bare minimum schema additions around your API so that the gateway will recognize your schema.\nTo actually enable entity resolution you will need to do a bit of leg work.")]),t._v(" "),a("p",[t._v('First, any types that will be "resolvable" need to be annotated with a '),a("code",[t._v("@key")]),t._v(" directive. You can use a helper function found\nin the "),a("code",[t._v("federation")]),t._v(" package to help with that.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLKey")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("The "),a("code",[t._v('"name"')]),t._v(" field is a field selector minus the outer braces.")]),t._v(" "),a("p",[t._v("If you need to extend a type from another service, you will need to define a stub version of it in the current service\nand annotate it with the "),a("code",[t._v("@extends")]),t._v(" annotation")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLKey")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"season episode"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n"),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLExtend")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Episode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLExternal")]),t._v(" season"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLExternal")]),t._v(" episode"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cast"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("Note the additional annotations we needed in this case. "),a("code",[t._v("Extend")]),t._v(" is needed to tell the gateway that this type is defined within\nanother service, while the "),a("code",[t._v("External")]),t._v(" flags these fields as being owned by the other service (there are several other annotations\navailable that you are encouraged to read about).")]),t._v(" "),a("p",[t._v("Once you have annotated your types, you need to tell "),a("code",[t._v("Federation")]),t._v(" how to resolve those types. Federation uses a slightly\ndifferent mechanism in resolving types from a standard GraphQL query, so for each type that you wish to support, you will\nneed to add an "),a("code",[t._v("EntityResolver")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("EntityResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterService"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CharacterArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" \n ZQuery"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getCharacter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n")])])]),a("p",[a("code",[t._v("EntityResolvers")]),t._v(' like normal field resolvers also supports a "metadata" variant which can be used to inspect the requested\nfields and potentially optimize the resulting query. You can use the provided helper method if you need to access the metadata field:')]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("EntityResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromMetadata"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" args "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fields"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("forall"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" ZQuery"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Nil"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" ZQuery"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getCharacter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("In the above we need to define an resolver which takes an "),a("code",[t._v("R")]),t._v(" environment type,\nan "),a("code",[t._v("A")]),t._v(" which has an implicit "),a("code",[t._v("ArgBuilder")]),t._v(" and an "),a("code",[t._v("Option[Out]")]),t._v(" where "),a("code",[t._v("Out")]),t._v(" has an implicit\n"),a("code",[t._v("Schema[R, Out]")]),t._v(" available. Creating the above we can now add these resolvers to our federated schema like so:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("schema @@ federated"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("aResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" additionalResolvers"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("You can now use the resulting "),a("code",[t._v("GraphQL[R]")]),t._v(" to start querying. You can also see the full code example "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/federation",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1)]),t._v(" "),a("h2",{attrs:{id:"tracing"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#tracing"}},[t._v("#")]),t._v(" Tracing")]),t._v(" "),a("p",[t._v("Federated tracing is slightly different from standard apollo-tracing thus it comes with its own wrapper defined in the "),a("code",[t._v("caliban-federation")]),t._v(" module.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("federation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tracing"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ApolloFederatedTracing\n\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" schema @@ federated"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" additionalResolvers"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" _"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@ ApolloFederatedTracing"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("In federated tracing the gateway communicates with the implementing service via a header "),a("code",[t._v("apollo-federation-include-trace")]),t._v(",\nfor now the only value it can send is "),a("code",[t._v("ftv1")]),t._v(". Thus if you detect this header then you should enable tracing otherwise you can disable it.")]),t._v(" "),a("p",[t._v("If you are using one of the wrappers you are done, they will automatically detect when the gateway\nenables tracing on a request. However, if you are calling the "),a("code",[t._v("interpreter.execute")]),t._v(" independently or you have some other custom\nset up you will need to add one more step to enable tracing.")]),t._v(" "),a("p",[t._v("If you wish to enable it manually (after detecting the header with your preferred framework) you can call: "),a("code",[t._v("request.withFederatedTracing")]),t._v(" which will return a new "),a("code",[t._v("GraphQLRequest")]),t._v(" that informs the wrapper\nthat it should include tracing data as part of the response extensions.")]),t._v(" "),a("h2",{attrs:{id:"federation-v2"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#federation-v2"}},[t._v("#")]),t._v(" Federation V2")]),t._v(" "),a("p",[t._v("Caliban can support the v2 federation specification as well. If your gateway supports the "),a("a",{attrs:{href:"https://www.apollographql.com/docs/federation/federation-spec",target:"_blank",rel:"noopener noreferrer"}},[t._v("Federation V2 specification"),a("OutboundLink")],1),t._v(", you can specify the supported feature set\nby using "),a("code",[t._v("caliban.federation.v2_x")]),t._v(" where "),a("code",[t._v("x")]),t._v(" is the minor version of the specification you wish to use.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Directive")]),t._v(" "),a("th",[t._v("Caliban Type")]),t._v(" "),a("th",[t._v("Version")]),t._v(" "),a("th",[t._v("Caliban package")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("@shareable")])]),t._v(" "),a("td",[a("code",[t._v("@GQLShareable")])]),t._v(" "),a("td",[t._v("v2.0")]),t._v(" "),a("td",[a("code",[t._v("caliban.federation.v2_0")])])]),t._v(" "),a("tr",[a("td",[a("code",[t._v("@inaccessable")])]),t._v(" "),a("td",[a("code",[t._v("@GQLInaccessible")])]),t._v(" "),a("td",[t._v("v2.0")]),t._v(" "),a("td",[a("code",[t._v("caliban.federation.v2_0")])])]),t._v(" "),a("tr",[a("td",[a("code",[t._v("@override")])]),t._v(" "),a("td",[a("code",[t._v("@GQLOverride")])]),t._v(" "),a("td",[t._v("v2.0")]),t._v(" "),a("td",[a("code",[t._v("caliban.federation.v2_0")])])]),t._v(" "),a("tr",[a("td",[a("code",[t._v("@tag")])]),t._v(" "),a("td",[a("code",[t._v("@GQLTag")])]),t._v(" "),a("td",[t._v("v2.0")]),t._v(" "),a("td",[a("code",[t._v("caliban.federation.v2_0")])])]),t._v(" "),a("tr",[a("td",[a("code",[t._v("@composeDirective")])]),t._v(" "),a("td",[a("code",[t._v("ComposeDirective")])]),t._v(" "),a("td",[t._v("v2.1")]),t._v(" "),a("td",[a("code",[t._v("caliban.federation.v2_1")])])]),t._v(" "),a("tr",[a("td",[a("code",[t._v("@interfaceObject")])]),t._v(" "),a("td",[a("code",[t._v("@GQLInterfaceObject")])]),t._v(" "),a("td",[t._v("v2.3")]),t._v(" "),a("td",[a("code",[t._v("caliban.federation.v2_3")])])])])]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("GQLKey")]),t._v(" field now also supports the "),a("code",[t._v("resolvable")]),t._v(" argument.")]),t._v(" "),a("p",[t._v("Using the new "),a("code",[t._v("federated")]),t._v(" aspect from any v2_x package will automatically make your graph available as a v2 schema,\neven if you aren't using the new directives.")]),t._v(" "),a("p",[t._v("For more information see the "),a("a",{attrs:{href:"https://www.apollographql.com/docs/federation/federation-2/new-in-federation-2/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Federation V2 specification"),a("OutboundLink")],1),t._v(".")]),t._v(" "),a("h3",{attrs:{id:"customizing-federation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#customizing-federation"}},[t._v("#")]),t._v(" Customizing Federation")]),t._v(" "),a("p",[t._v("Federation 2.1 introduced a new schema level directive called "),a("code",[t._v("@composeDirective")]),t._v(" which allows you to specify custom directives that should\nbe visible to clients of the gateway (by default all directives are hidden to clients of the gateway)")]),t._v(" "),a("p",[t._v("GraphQL federation is an evolving specification and not all routers support all features.\nCaliban provides support for "),a("code",[t._v("v2.0")]),t._v(", "),a("code",[t._v("v2.1")]),t._v(" and "),a("code",[t._v("v2.3")]),t._v(" of the specification. If you need to use\nan earlier version or you need to customize some aspect of the federation directives (for instance by providing your own "),a("code",[t._v("@composeDirective")]),t._v("s) you can do so by simply extending the "),a("code",[t._v("FederationV2")]),t._v(" class.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// With a package object but you can also create a normal object")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("object")]),t._v(" myFederation "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" FederationV2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Versions"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v2_3 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("::")]),t._v(" \n Link"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https://myspecs.dev/myDirective/v1.0"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Import"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@myDirective"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Import"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@anotherDirective"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" as "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@hello"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("::")]),t._v(" \n ComposeDirective"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@myDirective"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("::")]),t._v(" \n ComposeDirective"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@hello"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("::")]),t._v(" Nil\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("with")]),t._v(" FederationDirectivesV2_3\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Then import your new federation object instead of `caliban.federation.v2_3`")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("myFederation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n")])])])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/31.1784d0cb.js b/docs/assets/js/31.33bf616d.js similarity index 99% rename from docs/assets/js/31.1784d0cb.js rename to docs/assets/js/31.33bf616d.js index 024baa7634..01ab09d99e 100644 --- a/docs/assets/js/31.1784d0cb.js +++ b/docs/assets/js/31.33bf616d.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[31],{313:function(t,a,s){"use strict";s.r(a);var n=s(14),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"laminext-integration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#laminext-integration"}},[t._v("#")]),t._v(" Laminext Integration")]),t._v(" "),a("p",[t._v("If you are using the Scala.js framework "),a("a",{attrs:{href:"https://laminar.dev",target:"_blank",rel:"noopener noreferrer"}},[t._v("Laminar"),a("OutboundLink")],1),t._v(", there is a module that makes the integration even nicer, with support for subscriptions.\nIt is depending on "),a("a",{attrs:{href:"https://laminext.dev",target:"_blank",rel:"noopener noreferrer"}},[t._v("Laminext"),a("OutboundLink")],1),t._v(", a library that provides nice little helpers for Laminar, in particular for using "),a("code",[t._v("Fetch")]),t._v(" and "),a("code",[t._v("WebSocket")]),t._v(".")]),t._v(" "),a("p",[t._v("To use it, import the "),a("code",[t._v("caliban-client-laminext")]),t._v(" module:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-client-laminext"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),t._v("\n")])])]),a("p",[t._v("Add the following import to your code:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("client"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("laminext"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n")])])]),a("p",[t._v("This import adds an extension method "),a("code",[t._v("toEventStream(uri)")]),t._v(" to "),a("code",[t._v("SelectionBuilder")]),t._v(", which is similar to "),a("code",[t._v("toRequest")]),t._v(" except it creates an "),a("code",[t._v("EventStream")]),t._v(" instead of an sttp "),a("code",[t._v("Request")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" characters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Var"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Var"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Nil"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" uri "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://localhost:8088/api/graphql"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" getCharacters "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Client"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toEventStream"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("uri"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" view"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Div "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" \n div"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Characters: "')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n getCharacters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("collectRight "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("set _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n child "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("signal"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" div"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mkString"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('", "')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("To use subscriptions, you first need to create a "),a("code",[t._v("WebSocket")]),t._v(" with protocol "),a("code",[t._v("graphql-ws")]),t._v(". Use the extension method "),a("code",[t._v(".graphql")]),t._v(" instead of "),a("code",[t._v(".text")]),t._v(" or "),a("code",[t._v(".json")]),t._v(".\nThen use the extension method "),a("code",[t._v("toSubscription")]),t._v(" on your "),a("code",[t._v("SelectionBuilder")]),t._v(" and pass the "),a("code",[t._v("WebSocket")]),t._v(" object.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" ws "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" WebSocket"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("url"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ws://localhost:8088/ws/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"graphql-ws"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("graphql"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("build"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" deletedCharacters "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Subscriptions"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characterDeleted"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toSubscription"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ws"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("Finally, you can use "),a("code",[t._v("ws.connect")]),t._v(" to connect the "),a("code",[t._v("WebSocket")]),t._v(", "),a("code",[t._v("ws.init()")]),t._v(" to initialize the communication with the graphql server and "),a("code",[t._v(".received")]),t._v(" to get an "),a("code",[t._v("EventStream")]),t._v(" of the type returned by your subscription.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("ws"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("connect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\nws"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("connected\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ws"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("init"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("flatMap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" deletedCharacters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("received"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("collectRight"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("update"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("filterNot"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_ "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n")])])]),a("p",[t._v("There is a full example in the "),a("code",[t._v("test")]),t._v(" folder of the "),a("code",[t._v("caliban-client-laminext")]),t._v(" module.\nTo use it:")]),t._v(" "),a("ul",[a("li",[t._v("run "),a("code",[t._v("ExampleApp")]),t._v(" of the http4s server example (it supports CORS)")]),t._v(" "),a("li",[t._v("run "),a("code",[t._v("clientLaminextJS/Test/fastLinkJS")]),t._v(" to compile the Scala.js code")]),t._v(" "),a("li",[t._v("run "),a("code",[t._v("yarn install")]),t._v(" and "),a("code",[t._v("yarn exec vite")]),t._v(" in the "),a("code",[t._v("caliban-client-laminext")]),t._v(" folder")]),t._v(" "),a("li",[t._v("the example page will be running on "),a("a",{attrs:{href:"http://localhost:3000",target:"_blank",rel:"noopener noreferrer"}},[t._v("http://localhost:3000"),a("OutboundLink")],1)])])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[31],{313:function(t,a,s){"use strict";s.r(a);var n=s(14),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"laminext-integration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#laminext-integration"}},[t._v("#")]),t._v(" Laminext Integration")]),t._v(" "),a("p",[t._v("If you are using the Scala.js framework "),a("a",{attrs:{href:"https://laminar.dev",target:"_blank",rel:"noopener noreferrer"}},[t._v("Laminar"),a("OutboundLink")],1),t._v(", there is a module that makes the integration even nicer, with support for subscriptions.\nIt is depending on "),a("a",{attrs:{href:"https://laminext.dev",target:"_blank",rel:"noopener noreferrer"}},[t._v("Laminext"),a("OutboundLink")],1),t._v(", a library that provides nice little helpers for Laminar, in particular for using "),a("code",[t._v("Fetch")]),t._v(" and "),a("code",[t._v("WebSocket")]),t._v(".")]),t._v(" "),a("p",[t._v("To use it, import the "),a("code",[t._v("caliban-client-laminext")]),t._v(" module:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-client-laminext"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),t._v("\n")])])]),a("p",[t._v("Add the following import to your code:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("client"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("laminext"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n")])])]),a("p",[t._v("This import adds an extension method "),a("code",[t._v("toEventStream(uri)")]),t._v(" to "),a("code",[t._v("SelectionBuilder")]),t._v(", which is similar to "),a("code",[t._v("toRequest")]),t._v(" except it creates an "),a("code",[t._v("EventStream")]),t._v(" instead of an sttp "),a("code",[t._v("Request")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" characters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Var"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Var"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Nil"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" uri "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://localhost:8088/api/graphql"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" getCharacters "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Client"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toEventStream"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("uri"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" view"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Div "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" \n div"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Characters: "')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n getCharacters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("collectRight "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("set _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n child "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("signal"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" div"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mkString"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('", "')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("To use subscriptions, you first need to create a "),a("code",[t._v("WebSocket")]),t._v(" with protocol "),a("code",[t._v("graphql-ws")]),t._v(". Use the extension method "),a("code",[t._v(".graphql")]),t._v(" instead of "),a("code",[t._v(".text")]),t._v(" or "),a("code",[t._v(".json")]),t._v(".\nThen use the extension method "),a("code",[t._v("toSubscription")]),t._v(" on your "),a("code",[t._v("SelectionBuilder")]),t._v(" and pass the "),a("code",[t._v("WebSocket")]),t._v(" object.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" ws "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" WebSocket"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("url"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ws://localhost:8088/ws/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"graphql-ws"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("graphql"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("build"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" deletedCharacters "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Subscriptions"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characterDeleted"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toSubscription"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ws"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("Finally, you can use "),a("code",[t._v("ws.connect")]),t._v(" to connect the "),a("code",[t._v("WebSocket")]),t._v(", "),a("code",[t._v("ws.init()")]),t._v(" to initialize the communication with the graphql server and "),a("code",[t._v(".received")]),t._v(" to get an "),a("code",[t._v("EventStream")]),t._v(" of the type returned by your subscription.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("ws"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("connect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\nws"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("connected\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ws"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("init"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("flatMap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" deletedCharacters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("received"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("collectRight"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("update"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("filterNot"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_ "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n")])])]),a("p",[t._v("There is a full example in the "),a("code",[t._v("test")]),t._v(" folder of the "),a("code",[t._v("caliban-client-laminext")]),t._v(" module.\nTo use it:")]),t._v(" "),a("ul",[a("li",[t._v("run "),a("code",[t._v("ExampleApp")]),t._v(" of the http4s server example (it supports CORS)")]),t._v(" "),a("li",[t._v("run "),a("code",[t._v("clientLaminextJS/Test/fastLinkJS")]),t._v(" to compile the Scala.js code")]),t._v(" "),a("li",[t._v("run "),a("code",[t._v("yarn install")]),t._v(" and "),a("code",[t._v("yarn exec vite")]),t._v(" in the "),a("code",[t._v("caliban-client-laminext")]),t._v(" folder")]),t._v(" "),a("li",[t._v("the example page will be running on "),a("a",{attrs:{href:"http://localhost:3000",target:"_blank",rel:"noopener noreferrer"}},[t._v("http://localhost:3000"),a("OutboundLink")],1)])])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/32.b1b1b9b3.js b/docs/assets/js/32.e98c24dd.js similarity index 99% rename from docs/assets/js/32.b1b1b9b3.js rename to docs/assets/js/32.e98c24dd.js index 08a99ebbfb..8be56d8116 100644 --- a/docs/assets/js/32.b1b1b9b3.js +++ b/docs/assets/js/32.e98c24dd.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[32],{314:function(t,a,s){"use strict";s.r(a);var n=s(14),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"middleware"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#middleware"}},[t._v("#")]),t._v(" Middleware")]),t._v(" "),a("p",[t._v("Caliban allows you to perform additional actions at various levels of a query processing, via the concept of "),a("code",[t._v("Wrapper")]),t._v(". Using wrappers, you can:")]),t._v(" "),a("ul",[a("li",[t._v("verify that a query doesn't reach some limit (e.g. depth, complexity)")]),t._v(" "),a("li",[t._v("modify a query before it's executed")]),t._v(" "),a("li",[t._v("add timeouts to queries or fields")]),t._v(" "),a("li",[t._v("log each field execution time")]),t._v(" "),a("li",[t._v("support "),a("a",{attrs:{href:"https://github.com/apollographql/apollo-tracing",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Tracing"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://www.apollographql.com/docs/apollo-server/performance/caching",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Caching"),a("OutboundLink")],1),t._v(" or anything similar")]),t._v(" "),a("li",[t._v("etc.")])]),t._v(" "),a("h2",{attrs:{id:"wrapper-types"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#wrapper-types"}},[t._v("#")]),t._v(" Wrapper types")]),t._v(" "),a("p",[t._v("There are 6 basic types of wrappers:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("OverallWrapper")]),t._v(" to wrap the whole query processing")]),t._v(" "),a("li",[a("code",[t._v("ParsingWrapper")]),t._v(" to wrap the query parsing only")]),t._v(" "),a("li",[a("code",[t._v("ValidationWrapper")]),t._v(" to wrap the query validation only")]),t._v(" "),a("li",[a("code",[t._v("ExecutionWrapper")]),t._v(" to wrap the query execution only")]),t._v(" "),a("li",[a("code",[t._v("FieldWrapper")]),t._v(" to wrap each field execution")]),t._v(" "),a("li",[a("code",[t._v("IntrospectionWrapper")]),t._v(" to wrap the introspection query only")])]),t._v(" "),a("p",[t._v("Each one requires a function that takes a "),a("code",[t._v("ZIO")]),t._v(" or "),a("code",[t._v("ZQuery")]),t._v(" computation together with some contextual information (e.g. the query string) and should return another computation.")]),t._v(" "),a("p",[t._v("Let's see how to implement a wrapper that times out the whole query if its processing takes longer than 1 minute.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrappers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Wrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" wrapper "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" OverallWrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" wrap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n process"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLRequest "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" GraphQLResponse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLRequest "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" GraphQLResponse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLRequest"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timeout"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.")]),t._v("minute"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getOrElse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GraphQLResponse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n NullValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Query was interrupted after 1 minute:\\n')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("query")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("You can also combine wrappers using "),a("code",[t._v("|+|")]),t._v(" and create a wrapper that requires an effect to be run at each query using "),a("code",[t._v("EffectfulWrapper")]),t._v(".")]),t._v(" "),a("p",[t._v("To use your wrapper, call "),a("code",[t._v("GraphQL#withWrapper")]),t._v(" or its alias "),a("code",[t._v("@@")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("withWrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("wrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@ wrapper\n")])])]),a("h2",{attrs:{id:"pre-defined-wrappers"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#pre-defined-wrappers"}},[t._v("#")]),t._v(" Pre-defined wrappers")]),t._v(" "),a("p",[t._v("Caliban comes with a few pre-made wrappers in "),a("code",[t._v("caliban.wrappers.Wrappers")]),t._v(":")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("maxDepth")]),t._v(" returns a wrapper that fails queries whose depth is higher than a given value")]),t._v(" "),a("li",[a("code",[t._v("maxFields")]),t._v(" returns a wrapper that fails queries whose number of fields is higher than a given value")]),t._v(" "),a("li",[a("code",[t._v("maxCost")]),t._v(" returns a wrapper that fails queries when the estimated cost of execution exceeds a given value")]),t._v(" "),a("li",[a("code",[t._v("queryCost")]),t._v(" returns a wrapper which adds an extension field that includes the cost of executing the query")]),t._v(" "),a("li",[a("code",[t._v("timeout")]),t._v(" returns a wrapper that fails queries taking more than a specified time")]),t._v(" "),a("li",[a("code",[t._v("printErrors")]),t._v(" returns a wrapper that prints errors")]),t._v(" "),a("li",[a("code",[t._v("printSlowQueries")]),t._v(" returns a wrapper that prints slow queries")]),t._v(" "),a("li",[a("code",[t._v("logSlowQueries")]),t._v(" returns a wrapper that logs slow queries via ZIO's built-in logging")]),t._v(" "),a("li",[a("code",[t._v("onSlowQueries")]),t._v(" returns a wrapper that can run a given function on slow queries")]),t._v(" "),a("li",[a("code",[t._v("metrics")]),t._v(" returns a wrapper that adds field-level metrics (count & duration) to the schema")])]),t._v(" "),a("p",[t._v("In addition to those, Caliban also ships with some non-spec but standard wrappers")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("caliban.wrappers.ApolloTracing.apolloTracing")]),t._v(" returns a wrapper that adds tracing data into the "),a("code",[t._v("extensions")]),t._v(" field of each response following "),a("a",{attrs:{href:"https://github.com/apollographql/apollo-tracing",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Tracing"),a("OutboundLink")],1),t._v(" format.")]),t._v(" "),a("li",[a("code",[t._v("caliban.wrappers.Caching.extension")]),t._v(" returns a wrapper that computes the total cache policy for a query and stores it in the extensions of the response. The result can then be used by http adapters to set the appropriate cache headers in the response.")]),t._v(" "),a("li",[a("code",[t._v("caliban.wrappers.ApolloPersistedQueries.apolloPersistedQueries")]),t._v(" returns a wrapper that caches and retrieves query using a hash using the "),a("a",{attrs:{href:"https://github.com/apollographql/apollo-link-persisted-queries",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Persisted Queries"),a("OutboundLink")],1),t._v(" format.")])]),t._v(" "),a("p",[t._v("They can be used like this:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n maxDepth"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("50")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n timeout"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v(" seconds"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n printSlowQueries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("500")]),t._v(" millis"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n apolloTracing"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n Caching"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extension")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h2",{attrs:{id:"wrapping-the-interpreter"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#wrapping-the-interpreter"}},[t._v("#")]),t._v(" Wrapping the interpreter")]),t._v(" "),a("p",[t._v("All the wrappers mentioned above require that you don't modify the environment "),a("code",[t._v("R")]),t._v(" and the error type which is always a "),a("code",[t._v("CalibanError")]),t._v(". It is also possible to wrap your "),a("code",[t._v("GraphQLInterpreter")]),t._v(" by calling "),a("code",[t._v("wrapExecutionWith")]),t._v(" on it. This method takes in a function "),a("code",[t._v("f")]),t._v(" and returns a new "),a("code",[t._v("GraphQLInterpreter")]),t._v(" that will wrap the "),a("code",[t._v("execute")]),t._v(" method with this function "),a("code",[t._v("f")]),t._v(".")]),t._v(" "),a("p",[t._v("It is used internally to implement "),a("code",[t._v("mapError")]),t._v(" (customize errors) and "),a("code",[t._v("provide")]),t._v(" (eliminate the environment), but you can use it for other purposes such as adding a general timeout, logging response times, etc.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// change error type to String")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i2"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mapError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toString"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// provide the environment")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i3"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("provide"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("myEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// add a timeout on every query execution")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i4"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrapExecutionWith"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timeout"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("30")]),t._v(" seconds"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getOrElse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GraphQLResponse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("NullValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Timeout!"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h2",{attrs:{id:"customizing-error-responses"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#customizing-error-responses"}},[t._v("#")]),t._v(" Customizing error responses")]),t._v(" "),a("p",[t._v("During various phases of executing a query, an error may occur. Caliban renders the different instances of "),a("code",[t._v("CalibanError")]),t._v(" to a GraphQL spec compliant response. As a user, you will most likely encounter "),a("code",[t._v("ExecutionError")]),t._v(" at some point because this will encapsulate the errors in the error channel of your effects. For Caliban to be able to render some basic message about the error that occured during query execution, it is important that your error extends "),a("code",[t._v("Throwable")]),t._v(".")]),t._v(" "),a("p",[t._v("For more meaningful error handling, GraphQL spec allows for an "),a("a",{attrs:{href:"http://spec.graphql.org/June2018/#example-fce18",target:"_blank",rel:"noopener noreferrer"}},[a("code",[t._v("extension")]),a("OutboundLink")],1),t._v(" object in the error response. This object may include, for instance, "),a("code",[t._v("code")]),t._v(" information to model enum-like error codes that can be handled by a front-end. In order to generate this information, one can use the "),a("code",[t._v("mapError")]),t._v(" function on a "),a("code",[t._v("GraphQLInterpreter")]),t._v(". An example is provided below in which we map a custom domain error within an "),a("code",[t._v("ExecutionError")]),t._v(" to a meaningful error code.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ResponseValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ObjectValue\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" ExampleAppEncodableError "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Throwable "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" errorCode"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" UnauthorizedError "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" ExampleAppEncodableError "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" errorCode"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"UNAUTHORIZED"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" withErrorCodeExtensions"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n interpreter"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" interpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mapError "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err @ ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("exampleError"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ExampleAppEncodableError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("extensions "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"errorCode"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("exampleError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("errorCode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ExecutionError "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("extensions "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"errorCode"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"EXECUTION_ERROR"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ValidationError "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("extensions "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"errorCode"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"VALIDATION_ERROR"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ParsingError "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("extensions "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"errorCode"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"PARSING_ERROR"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"wrapping-the-graphql"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#wrapping-the-graphql"}},[t._v("#")]),t._v(" Wrapping the GraphQL")]),t._v(" "),a("p",[t._v("If you need to implement new functionality that involves not just changes to execution but also to the underlying\nschema you can use the higher-level "),a("code",[t._v("GraphQLAspect")]),t._v(" which allows full control of the resulting "),a("code",[t._v("GraphQL")]),t._v(" that it wraps.")]),t._v(" "),a("p",[t._v("Here is such an example that is part of the "),a("code",[t._v("federation")]),t._v(" package which makes a schema available to be used as a sub-graph in\na federated graph:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" federate"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("original"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n _service"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" _Service"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n _fieldSet"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FieldSet "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" FieldSet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_service "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _Service"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("original"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("render"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" federationDirectives"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" original\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" federated"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLAspect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" GraphQLAspect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" apply"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("original"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n federate"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("original"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"cost-estimation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#cost-estimation"}},[t._v("#")]),t._v(" Cost Estimation")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("queryCost")]),t._v(" and "),a("code",[t._v("maxCost")]),t._v(" wrappers as well as their variants can be used to estimate the cost of a query, however they require a bit\nmore set up to work properly.")]),t._v(" "),a("p",[t._v("These wrappers are in the "),a("code",[t._v("CostEstimation")]),t._v(" object which also comes with a special directive that can be used out of the box to instrument your\nschema for cost analysis.")]),t._v(" "),a("p",[t._v("Given a schema in which different fields have different costs to execute, either because they require additional network or computing resources, or database access, or they\nhave some other dependency that makes them expensive to compute. You can add the "),a("code",[t._v("CostDirective")]),t._v(" to your resolver like so:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrappers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("CostEstimation\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrappers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("CostEstimation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" SpokenLineArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("offset"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" limit"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLCost")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Compute a realtime list of all the spoken lines for this character")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLCost")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" multipliers "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"limit"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n spokenLines"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SpokenLineArgs "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLCost")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" characters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" allCharacterNames"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" getLines"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" offset"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" limit"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n characters "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" allCharacterNames"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("flatMap "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" \n names "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("foreach"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("names"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" name "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" character "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n spokenLines "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" args "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" getLines"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("offset"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("limit"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" \n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" apiWithCost "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" api @@ \n queryCost @@ "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or queryCost(f: Field => Double) to specify your own field cost estimation")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or queryCostWith(f: Field => Double)(p: Double => URIO[R, Any]) to also specify a side effect after computing the total cost")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or queryCostZIO(f: Field => URIO[R, Double]) if your field calculation returns an effect")]),t._v("\n maxCost"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CostEstimation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("costDirective"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or maxCostOrError(maxCost)(f: Double => ValidationError) to specify a different error")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or maxCostZIO(maxCost)(f: Field => URIO[R, Double]) if your field calculation returns an effect")]),t._v("\n\n")])])]),a("p",[t._v('In the above example we have provided a couple different examples. For instance, we can add the directive to both types and\nto fields. In this case the field resolver will override the type cost, however if there is no field cost then the type cost will be used.\nWe may also specify a "multipliers" argument when using arguments. This will match the argument names and use numeric argument values to multiply the base value.\nIn the above case this means that a query that specifies a '),a("code",[t._v("limit")]),t._v(" of "),a("code",[t._v("10")]),t._v(" for the "),a("code",[t._v("spokenLines")]),t._v(" field will have the base field cost multipled by 10 resulting in a total cost\nof execution of "),a("code",[t._v("1000")])]),t._v(" "),a("h2",{attrs:{id:"opentelemetry-tracing"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#opentelemetry-tracing"}},[t._v("#")]),t._v(" OpenTelemetry Tracing")]),t._v(" "),a("p",[t._v("Caliban ships with support for OpenTelemetry tracing via integration with "),a("a",{attrs:{href:"https://github.com/zio/zio-telemetry",target:"_blank",rel:"noopener noreferrer"}},[t._v("zio-telemetry"),a("OutboundLink")],1),t._v(" in the "),a("code",[t._v("caliban-tracing")]),t._v(" package.")]),t._v(" "),a("p",[t._v("In order to use tracing, first add "),a("code",[t._v("caliban-tracing")]),t._v(" to your "),a("code",[t._v("built.sbt")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-tracing"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),t._v("\n")])])]),a("p",[t._v("Then add it to your schema as any other wrapper:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tracing"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("TracingWrapper\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("telemetry"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("opentelemetry"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Tracing\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" tracedApi "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" api @@ TracingWrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("traced\n")])])]),a("p",[t._v("This will now make sure that any effect (ZIO or ZQuery) is measured as its own span, which makes it easy to spot potential optimizations (such as sequential loading) in your schema.")]),t._v(" "),a("p",[t._v("More or less like this:")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("query |----------------------------------------------|\nfield a |-------|\nfield b |-------|\nnested field |-----------------------|\nnested field a |-------------------|\nnested field b |-------------------|\n")])])]),a("p",[t._v("which makes it easy to spot that e.g field a and field b could be resolved in parallel.")])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[32],{314:function(t,a,s){"use strict";s.r(a);var n=s(14),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"middleware"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#middleware"}},[t._v("#")]),t._v(" Middleware")]),t._v(" "),a("p",[t._v("Caliban allows you to perform additional actions at various levels of a query processing, via the concept of "),a("code",[t._v("Wrapper")]),t._v(". Using wrappers, you can:")]),t._v(" "),a("ul",[a("li",[t._v("verify that a query doesn't reach some limit (e.g. depth, complexity)")]),t._v(" "),a("li",[t._v("modify a query before it's executed")]),t._v(" "),a("li",[t._v("add timeouts to queries or fields")]),t._v(" "),a("li",[t._v("log each field execution time")]),t._v(" "),a("li",[t._v("support "),a("a",{attrs:{href:"https://github.com/apollographql/apollo-tracing",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Tracing"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://www.apollographql.com/docs/apollo-server/performance/caching",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Caching"),a("OutboundLink")],1),t._v(" or anything similar")]),t._v(" "),a("li",[t._v("etc.")])]),t._v(" "),a("h2",{attrs:{id:"wrapper-types"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#wrapper-types"}},[t._v("#")]),t._v(" Wrapper types")]),t._v(" "),a("p",[t._v("There are 6 basic types of wrappers:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("OverallWrapper")]),t._v(" to wrap the whole query processing")]),t._v(" "),a("li",[a("code",[t._v("ParsingWrapper")]),t._v(" to wrap the query parsing only")]),t._v(" "),a("li",[a("code",[t._v("ValidationWrapper")]),t._v(" to wrap the query validation only")]),t._v(" "),a("li",[a("code",[t._v("ExecutionWrapper")]),t._v(" to wrap the query execution only")]),t._v(" "),a("li",[a("code",[t._v("FieldWrapper")]),t._v(" to wrap each field execution")]),t._v(" "),a("li",[a("code",[t._v("IntrospectionWrapper")]),t._v(" to wrap the introspection query only")])]),t._v(" "),a("p",[t._v("Each one requires a function that takes a "),a("code",[t._v("ZIO")]),t._v(" or "),a("code",[t._v("ZQuery")]),t._v(" computation together with some contextual information (e.g. the query string) and should return another computation.")]),t._v(" "),a("p",[t._v("Let's see how to implement a wrapper that times out the whole query if its processing takes longer than 1 minute.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrappers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Wrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" wrapper "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" OverallWrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" wrap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n process"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLRequest "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" GraphQLResponse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLRequest "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" GraphQLResponse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLRequest"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timeout"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.")]),t._v("minute"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getOrElse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GraphQLResponse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n NullValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Query was interrupted after 1 minute:\\n')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("query")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("You can also combine wrappers using "),a("code",[t._v("|+|")]),t._v(" and create a wrapper that requires an effect to be run at each query using "),a("code",[t._v("EffectfulWrapper")]),t._v(".")]),t._v(" "),a("p",[t._v("To use your wrapper, call "),a("code",[t._v("GraphQL#withWrapper")]),t._v(" or its alias "),a("code",[t._v("@@")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("withWrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("wrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@ wrapper\n")])])]),a("h2",{attrs:{id:"pre-defined-wrappers"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#pre-defined-wrappers"}},[t._v("#")]),t._v(" Pre-defined wrappers")]),t._v(" "),a("p",[t._v("Caliban comes with a few pre-made wrappers in "),a("code",[t._v("caliban.wrappers.Wrappers")]),t._v(":")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("maxDepth")]),t._v(" returns a wrapper that fails queries whose depth is higher than a given value")]),t._v(" "),a("li",[a("code",[t._v("maxFields")]),t._v(" returns a wrapper that fails queries whose number of fields is higher than a given value")]),t._v(" "),a("li",[a("code",[t._v("maxCost")]),t._v(" returns a wrapper that fails queries when the estimated cost of execution exceeds a given value")]),t._v(" "),a("li",[a("code",[t._v("queryCost")]),t._v(" returns a wrapper which adds an extension field that includes the cost of executing the query")]),t._v(" "),a("li",[a("code",[t._v("timeout")]),t._v(" returns a wrapper that fails queries taking more than a specified time")]),t._v(" "),a("li",[a("code",[t._v("printErrors")]),t._v(" returns a wrapper that prints errors")]),t._v(" "),a("li",[a("code",[t._v("printSlowQueries")]),t._v(" returns a wrapper that prints slow queries")]),t._v(" "),a("li",[a("code",[t._v("logSlowQueries")]),t._v(" returns a wrapper that logs slow queries via ZIO's built-in logging")]),t._v(" "),a("li",[a("code",[t._v("onSlowQueries")]),t._v(" returns a wrapper that can run a given function on slow queries")]),t._v(" "),a("li",[a("code",[t._v("metrics")]),t._v(" returns a wrapper that adds field-level metrics (count & duration) to the schema")])]),t._v(" "),a("p",[t._v("In addition to those, Caliban also ships with some non-spec but standard wrappers")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("caliban.wrappers.ApolloTracing.apolloTracing")]),t._v(" returns a wrapper that adds tracing data into the "),a("code",[t._v("extensions")]),t._v(" field of each response following "),a("a",{attrs:{href:"https://github.com/apollographql/apollo-tracing",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Tracing"),a("OutboundLink")],1),t._v(" format.")]),t._v(" "),a("li",[a("code",[t._v("caliban.wrappers.Caching.extension")]),t._v(" returns a wrapper that computes the total cache policy for a query and stores it in the extensions of the response. The result can then be used by http adapters to set the appropriate cache headers in the response.")]),t._v(" "),a("li",[a("code",[t._v("caliban.wrappers.ApolloPersistedQueries.apolloPersistedQueries")]),t._v(" returns a wrapper that caches and retrieves query using a hash using the "),a("a",{attrs:{href:"https://github.com/apollographql/apollo-link-persisted-queries",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Persisted Queries"),a("OutboundLink")],1),t._v(" format.")])]),t._v(" "),a("p",[t._v("They can be used like this:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n maxDepth"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("50")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n timeout"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v(" seconds"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n printSlowQueries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("500")]),t._v(" millis"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n apolloTracing"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n Caching"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extension")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h2",{attrs:{id:"wrapping-the-interpreter"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#wrapping-the-interpreter"}},[t._v("#")]),t._v(" Wrapping the interpreter")]),t._v(" "),a("p",[t._v("All the wrappers mentioned above require that you don't modify the environment "),a("code",[t._v("R")]),t._v(" and the error type which is always a "),a("code",[t._v("CalibanError")]),t._v(". It is also possible to wrap your "),a("code",[t._v("GraphQLInterpreter")]),t._v(" by calling "),a("code",[t._v("wrapExecutionWith")]),t._v(" on it. This method takes in a function "),a("code",[t._v("f")]),t._v(" and returns a new "),a("code",[t._v("GraphQLInterpreter")]),t._v(" that will wrap the "),a("code",[t._v("execute")]),t._v(" method with this function "),a("code",[t._v("f")]),t._v(".")]),t._v(" "),a("p",[t._v("It is used internally to implement "),a("code",[t._v("mapError")]),t._v(" (customize errors) and "),a("code",[t._v("provide")]),t._v(" (eliminate the environment), but you can use it for other purposes such as adding a general timeout, logging response times, etc.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// change error type to String")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i2"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mapError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toString"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// provide the environment")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i3"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("provide"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("myEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// add a timeout on every query execution")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i4"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrapExecutionWith"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timeout"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("30")]),t._v(" seconds"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getOrElse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GraphQLResponse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("NullValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Timeout!"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h2",{attrs:{id:"customizing-error-responses"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#customizing-error-responses"}},[t._v("#")]),t._v(" Customizing error responses")]),t._v(" "),a("p",[t._v("During various phases of executing a query, an error may occur. Caliban renders the different instances of "),a("code",[t._v("CalibanError")]),t._v(" to a GraphQL spec compliant response. As a user, you will most likely encounter "),a("code",[t._v("ExecutionError")]),t._v(" at some point because this will encapsulate the errors in the error channel of your effects. For Caliban to be able to render some basic message about the error that occured during query execution, it is important that your error extends "),a("code",[t._v("Throwable")]),t._v(".")]),t._v(" "),a("p",[t._v("For more meaningful error handling, GraphQL spec allows for an "),a("a",{attrs:{href:"http://spec.graphql.org/June2018/#example-fce18",target:"_blank",rel:"noopener noreferrer"}},[a("code",[t._v("extension")]),a("OutboundLink")],1),t._v(" object in the error response. This object may include, for instance, "),a("code",[t._v("code")]),t._v(" information to model enum-like error codes that can be handled by a front-end. In order to generate this information, one can use the "),a("code",[t._v("mapError")]),t._v(" function on a "),a("code",[t._v("GraphQLInterpreter")]),t._v(". An example is provided below in which we map a custom domain error within an "),a("code",[t._v("ExecutionError")]),t._v(" to a meaningful error code.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ResponseValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ObjectValue\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" ExampleAppEncodableError "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Throwable "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" errorCode"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" UnauthorizedError "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" ExampleAppEncodableError "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" errorCode"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"UNAUTHORIZED"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" withErrorCodeExtensions"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n interpreter"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" interpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mapError "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err @ ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("exampleError"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ExampleAppEncodableError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("extensions "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"errorCode"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("exampleError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("errorCode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ExecutionError "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("extensions "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"errorCode"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"EXECUTION_ERROR"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ValidationError "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("extensions "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"errorCode"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"VALIDATION_ERROR"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ParsingError "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("extensions "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"errorCode"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"PARSING_ERROR"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"wrapping-the-graphql"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#wrapping-the-graphql"}},[t._v("#")]),t._v(" Wrapping the GraphQL")]),t._v(" "),a("p",[t._v("If you need to implement new functionality that involves not just changes to execution but also to the underlying\nschema you can use the higher-level "),a("code",[t._v("GraphQLAspect")]),t._v(" which allows full control of the resulting "),a("code",[t._v("GraphQL")]),t._v(" that it wraps.")]),t._v(" "),a("p",[t._v("Here is such an example that is part of the "),a("code",[t._v("federation")]),t._v(" package which makes a schema available to be used as a sub-graph in\na federated graph:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" federate"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("original"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n _service"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" _Service"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n _fieldSet"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FieldSet "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" FieldSet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_service "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _Service"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("original"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("render"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" federationDirectives"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" original\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" federated"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLAspect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" GraphQLAspect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" apply"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("original"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n federate"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("original"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"cost-estimation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#cost-estimation"}},[t._v("#")]),t._v(" Cost Estimation")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("queryCost")]),t._v(" and "),a("code",[t._v("maxCost")]),t._v(" wrappers as well as their variants can be used to estimate the cost of a query, however they require a bit\nmore set up to work properly.")]),t._v(" "),a("p",[t._v("These wrappers are in the "),a("code",[t._v("CostEstimation")]),t._v(" object which also comes with a special directive that can be used out of the box to instrument your\nschema for cost analysis.")]),t._v(" "),a("p",[t._v("Given a schema in which different fields have different costs to execute, either because they require additional network or computing resources, or database access, or they\nhave some other dependency that makes them expensive to compute. You can add the "),a("code",[t._v("CostDirective")]),t._v(" to your resolver like so:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrappers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("CostEstimation\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrappers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("CostEstimation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" SpokenLineArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("offset"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" limit"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLCost")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Compute a realtime list of all the spoken lines for this character")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLCost")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" multipliers "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"limit"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n spokenLines"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SpokenLineArgs "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLCost")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" characters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" allCharacterNames"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" getLines"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" offset"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" limit"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n characters "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" allCharacterNames"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("flatMap "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" \n names "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("foreach"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("names"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" name "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" character "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n spokenLines "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" args "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" getLines"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("offset"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("limit"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" \n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" apiWithCost "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" api @@ \n queryCost @@ "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or queryCost(f: Field => Double) to specify your own field cost estimation")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or queryCostWith(f: Field => Double)(p: Double => URIO[R, Any]) to also specify a side effect after computing the total cost")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or queryCostZIO(f: Field => URIO[R, Double]) if your field calculation returns an effect")]),t._v("\n maxCost"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CostEstimation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("costDirective"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or maxCostOrError(maxCost)(f: Double => ValidationError) to specify a different error")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or maxCostZIO(maxCost)(f: Field => URIO[R, Double]) if your field calculation returns an effect")]),t._v("\n\n")])])]),a("p",[t._v('In the above example we have provided a couple different examples. For instance, we can add the directive to both types and\nto fields. In this case the field resolver will override the type cost, however if there is no field cost then the type cost will be used.\nWe may also specify a "multipliers" argument when using arguments. This will match the argument names and use numeric argument values to multiply the base value.\nIn the above case this means that a query that specifies a '),a("code",[t._v("limit")]),t._v(" of "),a("code",[t._v("10")]),t._v(" for the "),a("code",[t._v("spokenLines")]),t._v(" field will have the base field cost multipled by 10 resulting in a total cost\nof execution of "),a("code",[t._v("1000")])]),t._v(" "),a("h2",{attrs:{id:"opentelemetry-tracing"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#opentelemetry-tracing"}},[t._v("#")]),t._v(" OpenTelemetry Tracing")]),t._v(" "),a("p",[t._v("Caliban ships with support for OpenTelemetry tracing via integration with "),a("a",{attrs:{href:"https://github.com/zio/zio-telemetry",target:"_blank",rel:"noopener noreferrer"}},[t._v("zio-telemetry"),a("OutboundLink")],1),t._v(" in the "),a("code",[t._v("caliban-tracing")]),t._v(" package.")]),t._v(" "),a("p",[t._v("In order to use tracing, first add "),a("code",[t._v("caliban-tracing")]),t._v(" to your "),a("code",[t._v("built.sbt")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-tracing"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),t._v("\n")])])]),a("p",[t._v("Then add it to your schema as any other wrapper:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tracing"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("TracingWrapper\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("telemetry"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("opentelemetry"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Tracing\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" tracedApi "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" api @@ TracingWrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("traced\n")])])]),a("p",[t._v("This will now make sure that any effect (ZIO or ZQuery) is measured as its own span, which makes it easy to spot potential optimizations (such as sequential loading) in your schema.")]),t._v(" "),a("p",[t._v("More or less like this:")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("query |----------------------------------------------|\nfield a |-------|\nfield b |-------|\nnested field |-----------------------|\nnested field a |-------------------|\nnested field b |-------------------|\n")])])]),a("p",[t._v("which makes it easy to spot that e.g field a and field b could be resolved in parallel.")])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/36.d71a9373.js b/docs/assets/js/36.16ab13ff.js similarity index 99% rename from docs/assets/js/36.d71a9373.js rename to docs/assets/js/36.16ab13ff.js index 3d8754af36..f12c338f71 100644 --- a/docs/assets/js/36.d71a9373.js +++ b/docs/assets/js/36.16ab13ff.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[36],{318:function(t,a,s){"use strict";s.r(a);var n=s(14),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"schema-reporting"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#schema-reporting"}},[t._v("#")]),t._v(" Schema Reporting")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("caliban-reporting")]),t._v(" module allows you to integrate with Apollo's "),a("a",{attrs:{href:"https://github.com/apollographql/apollo-schema-reporting-preview-docs/blob/master/schema-reporting-protocol.md",target:"_blank",rel:"noopener noreferrer"}},[t._v("schema reporting protocol"),a("OutboundLink")],1),t._v(".\nThis enables your servers to automatically publish updated schemas on start up without involving any additional tooling.")]),t._v(" "),a("p",[t._v("You can enable the settings by providing the "),a("code",[t._v("ReportingDaemon")]),t._v(" to your "),a("code",[t._v("Runtime")]),t._v(" during setup.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Define your GraphQL schema normally")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" \n graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Amos"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Define a SchemaReporter that will communicate with Apollo")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" reporterL "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" SchemaReporter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromDefaultConfig "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// Loads the access token from an environment variable called "APOLLO_KEY"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Or load it from a configuration type")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// val reporterL = ZLayer.service[ApolloConfig] >>> SchemaReporter.fromConfig[ApolloConfig](_.key)")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Define your graph references")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" daemon"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Scope "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("with")]),t._v(" ReportingDaemon"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n graph1 "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" SchemaReportingRef"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("make"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"my-graph@production"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// For dynamic or possibly updating schemas you can provide a Ref and a transform function that will allow")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// you to push schema updates that occur at runtime.")]),t._v("\n ref "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" Ref"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("make"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"schema { query: Query }\\n type Query { hello: String! }"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n graph2 "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" SchemaReportingRef"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromRef"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ref"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"dynamic-graph@production"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("identity"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ReportingDaemon"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("register"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("graph1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ReportingDaemon"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("register"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("graph2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Now wire it up")]),t._v("\nZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("scoped"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("daemon"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("provide"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("reporterL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" AsyncHttpClientZioBackend"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("layer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ReportingDaemon"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("live"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[36],{319:function(t,a,s){"use strict";s.r(a);var n=s(14),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"schema-reporting"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#schema-reporting"}},[t._v("#")]),t._v(" Schema Reporting")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("caliban-reporting")]),t._v(" module allows you to integrate with Apollo's "),a("a",{attrs:{href:"https://github.com/apollographql/apollo-schema-reporting-preview-docs/blob/master/schema-reporting-protocol.md",target:"_blank",rel:"noopener noreferrer"}},[t._v("schema reporting protocol"),a("OutboundLink")],1),t._v(".\nThis enables your servers to automatically publish updated schemas on start up without involving any additional tooling.")]),t._v(" "),a("p",[t._v("You can enable the settings by providing the "),a("code",[t._v("ReportingDaemon")]),t._v(" to your "),a("code",[t._v("Runtime")]),t._v(" during setup.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Define your GraphQL schema normally")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" \n graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Amos"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Define a SchemaReporter that will communicate with Apollo")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" reporterL "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" SchemaReporter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromDefaultConfig "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// Loads the access token from an environment variable called "APOLLO_KEY"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Or load it from a configuration type")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// val reporterL = ZLayer.service[ApolloConfig] >>> SchemaReporter.fromConfig[ApolloConfig](_.key)")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Define your graph references")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" daemon"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Scope "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("with")]),t._v(" ReportingDaemon"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n graph1 "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" SchemaReportingRef"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("make"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"my-graph@production"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// For dynamic or possibly updating schemas you can provide a Ref and a transform function that will allow")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// you to push schema updates that occur at runtime.")]),t._v("\n ref "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" Ref"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("make"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"schema { query: Query }\\n type Query { hello: String! }"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n graph2 "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" SchemaReportingRef"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromRef"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ref"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"dynamic-graph@production"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("identity"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ReportingDaemon"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("register"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("graph1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ReportingDaemon"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("register"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("graph2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Now wire it up")]),t._v("\nZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("scoped"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("daemon"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("provide"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("reporterL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" AsyncHttpClientZioBackend"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("layer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ReportingDaemon"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("live"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/37.27a657f8.js b/docs/assets/js/37.462d58e3.js similarity index 99% rename from docs/assets/js/37.27a657f8.js rename to docs/assets/js/37.462d58e3.js index f5cb8f5cf9..f6709e8a34 100644 --- a/docs/assets/js/37.27a657f8.js +++ b/docs/assets/js/37.462d58e3.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[37],{319:function(t,a,s){"use strict";s.r(a);var e=s(14),n=Object(e.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"schema-generation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#schema-generation"}},[t._v("#")]),t._v(" Schema generation")]),t._v(" "),a("p",[t._v("A GraphQL schema will be derived automatically at compile-time (no reflection) from the types present in your resolver.")]),t._v(" "),a("p",[t._v("If you're more interested in the schema-first approach, it is also possible to "),a("RouterLink",{attrs:{to:"/docs/server-codegen.html"}},[t._v("generate the Scala code from a GraphQL schema file")]),t._v(".")],1),t._v(" "),a("p",[t._v("The table below shows how common Scala types are converted to GraphQL types.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Scala Type")]),t._v(" "),a("th",[t._v("GraphQL Type")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[t._v("Boolean")]),t._v(" "),a("td",[t._v("Boolean")])]),t._v(" "),a("tr",[a("td",[t._v("Int")]),t._v(" "),a("td",[t._v("Int")])]),t._v(" "),a("tr",[a("td",[t._v("Float")]),t._v(" "),a("td",[t._v("Float")])]),t._v(" "),a("tr",[a("td",[t._v("Double")]),t._v(" "),a("td",[t._v("Float")])]),t._v(" "),a("tr",[a("td",[t._v("String")]),t._v(" "),a("td",[t._v("String")])]),t._v(" "),a("tr",[a("td",[t._v("java.util.UUID")]),t._v(" "),a("td",[t._v("ID")])]),t._v(" "),a("tr",[a("td",[t._v("Unit")]),t._v(" "),a("td",[t._v("Unit (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("Long")]),t._v(" "),a("td",[t._v("Long (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("BigInt")]),t._v(" "),a("td",[t._v("BigInt (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("BigDecimal")]),t._v(" "),a("td",[t._v("BigDecimal (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.Instant")]),t._v(" "),a("td",[t._v("Instant (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.LocalDate")]),t._v(" "),a("td",[t._v("LocalDate (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.LocalTime")]),t._v(" "),a("td",[t._v("LocalTime (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.LocalDateTime")]),t._v(" "),a("td",[t._v("LocalDateTime (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.OffsetDateTime")]),t._v(" "),a("td",[t._v("OffsetDateTime (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.ZonedDateTime")]),t._v(" "),a("td",[t._v("ZonedDateTime (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("Case Class")]),t._v(" "),a("td",[t._v("Object")])]),t._v(" "),a("tr",[a("td",[t._v("Sealed Trait")]),t._v(" "),a("td",[t._v("Enum, Union or Interface (see "),a("a",{attrs:{href:"#enums-unions-interfaces"}},[t._v("below")]),t._v(")")])]),t._v(" "),a("tr",[a("td",[t._v("Option[A]")]),t._v(" "),a("td",[t._v("Nullable A")])]),t._v(" "),a("tr",[a("td",[t._v("List[A]")]),t._v(" "),a("td",[t._v("List of A")])]),t._v(" "),a("tr",[a("td",[t._v("Set[A]")]),t._v(" "),a("td",[t._v("List of A")])]),t._v(" "),a("tr",[a("td",[t._v("Seq[A]")]),t._v(" "),a("td",[t._v("List of A")])]),t._v(" "),a("tr",[a("td",[t._v("Vector[A]")]),t._v(" "),a("td",[t._v("List of A")])]),t._v(" "),a("tr",[a("td",[t._v("A => B")]),t._v(" "),a("td",[t._v("A and B")])]),t._v(" "),a("tr",[a("td",[t._v("(A, B)")]),t._v(" "),a("td",[t._v("Object with 2 fields "),a("code",[t._v("_1")]),t._v(" and "),a("code",[t._v("_2")])])]),t._v(" "),a("tr",[a("td",[t._v("Either[A, B]")]),t._v(" "),a("td",[t._v("Object with 2 nullable fields "),a("code",[t._v("left")]),t._v(" and "),a("code",[t._v("right")])])]),t._v(" "),a("tr",[a("td",[t._v("Map[A, B]")]),t._v(" "),a("td",[t._v("List of Object with 2 fields "),a("code",[t._v("key")]),t._v(" and "),a("code",[t._v("value")])])]),t._v(" "),a("tr",[a("td",[t._v("ZIO[R, Nothing, A]")]),t._v(" "),a("td",[t._v("A")])]),t._v(" "),a("tr",[a("td",[t._v("ZIO[R, Throwable, A]")]),t._v(" "),a("td",[t._v("Nullable A")])]),t._v(" "),a("tr",[a("td",[t._v("Future[A]")]),t._v(" "),a("td",[t._v("Nullable A")])]),t._v(" "),a("tr",[a("td",[t._v("ZStream[R, Throwable, A]")]),t._v(" "),a("td",[t._v("A (subscription) or List of A (query, mutation)")])]),t._v(" "),a("tr",[a("td",[t._v("Json (from "),a("a",{attrs:{href:"https://github.com/circe/circe",target:"_blank",rel:"noopener noreferrer"}},[t._v("Circe"),a("OutboundLink")],1),t._v(")")]),t._v(" "),a("td",[t._v("Json (custom scalar, need "),a("code",[t._v("import caliban.interop.circe.json._")]),t._v(")")])]),t._v(" "),a("tr",[a("td",[t._v("Json (from "),a("a",{attrs:{href:"https://github.com/playframework/play-json",target:"_blank",rel:"noopener noreferrer"}},[t._v("play-json"),a("OutboundLink")],1),t._v(")")]),t._v(" "),a("td",[t._v("Json (custom scalar, need "),a("code",[t._v("import caliban.interop.play.json._")]),t._v(")")])])])]),t._v(" "),a("p",[t._v("See the "),a("a",{attrs:{href:"#custom-types"}},[t._v("Custom Types")]),t._v(" section to find out how to support your own types.")]),t._v(" "),a("p",[t._v("If you want Caliban to support other standard types, feel free to "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/issues",target:"_blank",rel:"noopener noreferrer"}},[t._v("file an issue"),a("OutboundLink")],1),t._v(" or even a PR.")]),t._v(" "),a("h2",{attrs:{id:"enums-unions-interfaces"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#enums-unions-interfaces"}},[t._v("#")]),t._v(" Enums, unions, interfaces")]),t._v(" "),a("p",[t._v("A sealed trait will be converted to a different GraphQL type depending on its content:")]),t._v(" "),a("ul",[a("li",[t._v("a sealed trait with only case objects will be converted to an "),a("code",[t._v("ENUM")])]),t._v(" "),a("li",[t._v("a sealed trait with only case classes will be converted to a "),a("code",[t._v("UNION")])])]),t._v(" "),a("p",[t._v('GraphQL does not support empty objects, so in case a sealed trait mixes case classes and case objects, a union type will be created and the case objects will have a "fake" field named '),a("code",[t._v("_")]),t._v(" which is not queryable.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Origin\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Origin "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" EARTH "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" MARS "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" BELT "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("The snippet above will produce the following GraphQL type:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("enum")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("BELT")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("EARTH")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("MARS")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Here's an example of union:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Role\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Role "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Captain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("shipName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Engineer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("specialty"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Mechanic "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("The snippet above will produce the following GraphQL type:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("union")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Role")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Captain")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Engineer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Mechanic")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Captain")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("shipName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Engineer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("specialty")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mechanic")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("Boolean")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("If your type needs to be shared between multiple unions you can use the "),a("code",[t._v("@GQLValueType")]),t._v(" annotation to have caliban\nproxy to another type beyond the sealed trait.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Pilot"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("callSign"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Role\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Role "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Captain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("shipName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Engineer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("specialty"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLValueType")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Proxy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("pilot"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Pilot"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("This will produce the following GraphQL Types:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("union")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Role")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Captain")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Engineer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Pilot")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Captain")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("shipName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Engineer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("specialty")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Pilot")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("callSign")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("If you prefer an "),a("code",[t._v("Interface")]),t._v(" instead of a "),a("code",[t._v("Union")]),t._v(" type, add the "),a("code",[t._v("@GQLInterface")]),t._v(" annotation to your sealed trait.\nAn interface will be created with all the fields that are common to the case classes extending the sealed trait, as long as they return the same type.")]),t._v(" "),a("p",[t._v("If you prefer to have a "),a("code",[t._v("Union")]),t._v(" type instead of an "),a("code",[t._v("Enum")]),t._v(", even when the sealed trait contains only objects, add the "),a("code",[t._v("@GQLUnion")]),t._v(" annotation.")]),t._v(" "),a("h2",{attrs:{id:"case-classes-and-sealed-traits"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#case-classes-and-sealed-traits"}},[t._v("#")]),t._v(" Case classes and sealed traits")]),t._v(" "),a("p",[t._v("The transformation between Scala types and GraphQL types is handled by a typeclass named "),a("code",[t._v("Schema")]),t._v(". As mentioned earlier, Caliban provides instances of "),a("code",[t._v("Schema")]),t._v(" for all basic Scala types, but inevitably you will need to support your own types, in particular case classes and sealed traits.")]),t._v(" "),a("p",[t._v("Caliban is able to generate instances of "),a("code",[t._v("Schema")]),t._v(" for case classes and sealed traits. You have two choices for doing that: auto derivation and semi-auto derivation.")]),t._v(" "),a("h3",{attrs:{id:"auto-derivation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#auto-derivation"}},[t._v("#")]),t._v(" Auto derivation")]),t._v(" "),a("p",[t._v("Auto derivation is achieved easily by adding the following import:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n")])])]),a("p",[t._v("Using this import, Caliban will generate "),a("code",[t._v("Schema")]),t._v(" instances for all the case classes and sealed traits that are found inside your resolver.")]),t._v(" "),a("div",{staticClass:"custom-block warning"},[a("p",{staticClass:"custom-block-title"},[t._v("Limitations")]),t._v(" "),a("p",[t._v("Auto derivation is the easiest way to get started, but it has some drawbacks:")]),t._v(" "),a("ul",[a("li",[t._v("If a type is referenced in several places inside your resolver, a "),a("code",[t._v("Schema")]),t._v(" will be generated for each occurrence, which can lead to longer compilation times and a high amount of generated code (a sign of this is that the compiler will suggest increasing "),a("code",[t._v("-Xmax-inlines")]),t._v(" in Scala 3).")]),t._v(" "),a("li",[t._v("When a "),a("code",[t._v("Schema")]),t._v(" is missing for a nested type inside your resolver, it can sometimes be difficult to find out which type is missing when using auto derivation, because the error message will mention the root type and not the nested one.")]),t._v(" "),a("li",[t._v("The macro that generates the "),a("code",[t._v("Schema")]),t._v(" instances sometimes gets confused when there are a lot of nested or recursive types, and can mistakenly generate a "),a("code",[t._v("Schema")]),t._v(" for types that already have a "),a("code",[t._v("Schema")]),t._v(" in scope. For this reason, semi-auto derivation is recommended for non-trivial schemas.")])])]),t._v(" "),a("h3",{attrs:{id:"semi-auto-derivation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#semi-auto-derivation"}},[t._v("#")]),t._v(" Semi-auto derivation")]),t._v(" "),a("p",[t._v("Semi-auto derivation is achieved as follows for each type that needs a "),a("code",[t._v("Schema")]),t._v(" instance ("),a("code",[t._v("MyClass")]),t._v(" in the example):")]),t._v(" "),a("code-group",[a("code-block",{attrs:{title:"Scala 2",active:""}},[a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schemaForMyClass"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3"}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SemiAuto\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if you don't want to use the `derives` syntax, you can also use the following:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])])])],1),t._v(" "),a("p",[t._v("In Scala 3, derivation doesn't support value classes and opaque types. You can use "),a("code",[t._v("Schema.genDebug")]),t._v(" to print the generated code in the console.")]),t._v(" "),a("h3",{attrs:{id:"combining-auto-and-semi-auto-derivation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#combining-auto-and-semi-auto-derivation"}},[t._v("#")]),t._v(" Combining auto and semi-auto derivation")]),t._v(" "),a("p",[t._v("For some types such as enums, it might be desirable to use auto derivation to reduce boilerplate schema definitions:")]),t._v(" "),a("code-group",[a("code-block",{attrs:{title:"Scala 2",active:""}},[a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Origin\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Origin "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" EARTH "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" MARS "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" BELT "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schemaForMyClass"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3 (Any schema)"}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("enum")]),t._v(" Origin "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Auto "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" EARTH"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MARS"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" BELT\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if you don't want to use the `derives` syntax, you can also use the following:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("derived\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3 (Custom schema)"}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("SchemaDerivation\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" MyEnv\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" EnvSchema "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" SchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("enum")]),t._v(" Origin "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" EnvSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Auto "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" EARTH"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MARS"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" BELT\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if you don't want to use the `derives` syntax:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" EnvSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("derived\n")])])])])],1),t._v(" "),a("h3",{attrs:{id:"deriving-fields-from-case-class-methods-scala-3-only"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#deriving-fields-from-case-class-methods-scala-3-only"}},[t._v("#")]),t._v(" Deriving fields from case class methods (Scala 3 only)")]),t._v(" "),a("p",[t._v("In certain cases, your type might contain fields whose value depends on other fields. For example, you might have a "),a("code",[t._v("Person")]),t._v(" type with a "),a("code",[t._v("fullName")]),t._v(" field that is derived from the "),a("code",[t._v("firstName")]),t._v(" and "),a("code",[t._v("lastName")]),t._v(" fields. In this case, you can use the "),a("code",[t._v("@GQLField")]),t._v(" annotation to indicate that the field should be derived from the method with the same name.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Annotations"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("GQLField\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Person"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n firstName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n lastName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SemiAuto "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLField")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" fullName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("firstName")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v(" ")]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("lastName")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("This case class will generate the following GraphQL type:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Person")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("firstName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("lastName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("fullName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("The methods annotated with "),a("code",[t._v("@GQLField")]),t._v(" can return any type for which a "),a("code",[t._v("Schema")]),t._v(" is defined for, including effects such as "),a("code",[t._v("ZIO")]),t._v(" and "),a("code",[t._v("ZQuery")]),t._v(".\nIn addition, you can use any other annotation that is supported for case class arguments, such as "),a("code",[t._v("@GQLName")]),t._v(", "),a("code",[t._v("@GQLDescription")]),t._v(" and "),a("code",[t._v("@GQLDeprecated")]),t._v(".")]),t._v(" "),a("p",[t._v("To reduce boilerplate of annotating a lot of methods with "),a("code",[t._v("@GQLField")]),t._v(", Caliban also provides the "),a("code",[t._v("@GQLFieldsFromMethods")]),t._v(" annotation that can be used to derive fields from all methods in a case class / case object.")]),t._v(" "),a("p",[t._v("For demonstration purposes (only!), the example above can be rewritten as follows:")]),t._v(" "),a("div",{staticClass:"language-scala 3 extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Annotations"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("GQLFieldsFromMethods\n\n"),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLFieldsFromMethods")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Person"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n fullName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SemiAuto "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" split "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" fullName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("split"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('" "')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" firstName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" split"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("head\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" lastName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" split"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("last\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[t._v("Annotate a public method with "),a("code",[t._v("@GQLExcluded")]),t._v(" to exclude it from field derivation.")])]),t._v(" "),a("div",{staticClass:"custom-block warning"},[a("p",{staticClass:"custom-block-title"},[t._v("Caveats")]),t._v(" "),a("p",[t._v("Derivation of fields via the "),a("code",[t._v("@GQLField")]),t._v(" / "),a("code",[t._v("@GQLFieldsFromMethods")]),t._v(" annotation can be convenient in certain cases, but has the following limitations:")]),t._v(" "),a("ul",[a("li",[t._v("The method cannot take arguments. If you need to derive a field that requires arguments, you can return a function instead.")]),t._v(" "),a("li",[t._v("The method must be public (i.e. not "),a("code",[t._v("private")]),t._v(" or "),a("code",[t._v("protected")]),t._v(").")]),t._v(" "),a("li",[t._v("It currently only works with methods (i.e., "),a("code",[t._v("def")]),t._v("). If you need to cache the output of the method, you can create a private lazy val and return it from the method.")]),t._v(" "),a("li",[t._v("It is not compatible with ahead-of-time compilation (e.g., generating a GraalVM native-image executable).")])])]),t._v(" "),a("h2",{attrs:{id:"arguments"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#arguments"}},[t._v("#")]),t._v(" Arguments")]),t._v(" "),a("p",[t._v("To declare a field that take arguments, create a dedicated case class representing the arguments and make the field a "),a("em",[t._v("function")]),t._v(" from this class to the result type.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" origin"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" FilterArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("origin"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FilterArgs "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("The snippet above will produce the following GraphQL type:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Queries")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("characters")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("origin")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Caliban provides auto-derivation for common types such as "),a("code",[t._v("Int")]),t._v(", "),a("code",[t._v("String")]),t._v(", "),a("code",[t._v("List")]),t._v(", "),a("code",[t._v("Option")]),t._v(", etc. but you can also support your own types by providing an implicit instance of "),a("code",[t._v("ArgBuilder")]),t._v(" that defines how incoming arguments from that types should be extracted. You also need a "),a("code",[t._v("Schema")]),t._v(" for those types.")]),t._v(" "),a("p",[t._v("Derivation of "),a("code",[t._v("ArgBuilder")]),t._v(" for case classes works similarly to "),a("code",[t._v("Schema")]),t._v(" derivation. You can use auto derivation by adding the following import:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n")])])]),a("p",[t._v("Or you can use semi-auto derivation as follows:")]),t._v(" "),a("code-group",[a("code-block",{attrs:{title:"Scala 2",active:""}},[a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" argBuilderForMyClass"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schemaForMyClass"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3"}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SemiAuto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ArgBuilder\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if you don't want to use the `derives` syntax, you can also use the following:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])])])],1),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[t._v("There is no "),a("code",[t._v("ArgBuilder")]),t._v(" for tuples. If you have multiple arguments, use a case class containing all of them instead of a tuple.")])]),t._v(" "),a("h3",{attrs:{id:"input-objects"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#input-objects"}},[t._v("#")]),t._v(" Input objects")]),t._v(" "),a("p",[t._v("GraphQL input objects can be derived from case classes in the same way as arguments")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("firstName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" lastName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" NameArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("author"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" NameArgs "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("This will generate the following schema:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("input")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token atom-input class-name"}},[t._v("NameInput")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("firstName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("lastName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Queries")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("author")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token atom-input class-name"}},[t._v("NameInput")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h3",{attrs:{id:"oneof-input-objects"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#oneof-input-objects"}},[t._v("#")]),t._v(" "),a("code",[t._v("@oneOf")]),t._v(" input objects")]),t._v(" "),a("p",[t._v("A "),a("code",[t._v("@oneOf")]),t._v(" input object is a special type of input object, in which only one of its fields must be set by the client. It is especially useful when you want a user to be able to choose between several potential input types.\nThis feature is still an RFC and therefore not yet officially part of the GraphQL spec, but Caliban supports it!")]),t._v(" "),a("p",[t._v("To define a "),a("code",[t._v("@oneOf")]),t._v(" input object, you need to create a sealed trait (or an enum in Scala 3) with case classes that extend it. The case classes must have a single field, which is the field that the client can set. The sealed trait / enum must be annotated with "),a("code",[t._v("@GQLOneOfInput")]),t._v(".")]),t._v(" "),a("code-group",[a("code-block",{attrs:{title:"Sealed trait",active:""}},[a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Annotations"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("GQLOneOfInput\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("firstName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" lastName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLOneOfInput")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" AuthorInput\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" AuthorInput "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" ById"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" ByName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" AuthorArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lookup"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" AuthorInput"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("author"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" AuthorArgs "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Enum (Scala 3)"}},[a("div",{staticClass:"language-scala 3 mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Annotations"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("GQLOneOfInput\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("firstName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" lastName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLOneOfInput")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("enum")]),t._v(" AuthorInput "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" ById"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" ByName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" AuthorArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lookup"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" AuthorInput"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("author"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" AuthorArgs "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])],1),t._v(" "),a("p",[t._v("This will generate the following schema, and the validation will verify that only one of those fields is provided in incoming queries.")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("input")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token atom-input class-name"}},[t._v("NameInput")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("firstName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("lastName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("input")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token atom-input class-name"}},[t._v("AuthorInput")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@oneOf")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("id")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token atom-input class-name"}},[t._v("NameInput")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Queries")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("author")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("lookup")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token atom-input class-name"}},[t._v("AuthorInput")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("A few things to keep in mind when using "),a("code",[t._v("@oneOf")]),t._v(" input objects:")]),t._v(" "),a("ul",[a("li",[t._v("The leaf case classes must contain "),a("strong",[t._v("exactly 1 non-nullable field")]),t._v(". If you need more than one field, you should wrap them in a case class.")]),t._v(" "),a("li",[t._v("The field names in the leaf cases must be unique.")]),t._v(" "),a("li",[t._v("You must have a "),a("code",[t._v("Schema")]),t._v(" and an "),a("code",[t._v("ArgBuilder")]),t._v(" for any objects used in the leaf cases.")])]),t._v(" "),a("h2",{attrs:{id:"custom-types"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#custom-types"}},[t._v("#")]),t._v(" Custom types")]),t._v(" "),a("p",[t._v("Caliban provides auto-derivation for common types such as "),a("code",[t._v("Int")]),t._v(", "),a("code",[t._v("String")]),t._v(", "),a("code",[t._v("List")]),t._v(", "),a("code",[t._v("Option")]),t._v(", etc. but you can also support your own types by providing an implicit instance of "),a("code",[t._v("Schema")]),t._v(". Note that you don't have to do this if your types are just case classes composed of common types.")]),t._v(" "),a("p",[t._v("An easy way to do this is to reuse existing instances and use "),a("code",[t._v("contramap")]),t._v(" to map from your type to the original type. Here's an example of creating an instance for "),a("a",{attrs:{href:"https://github.com/fthomas/refined",target:"_blank",rel:"noopener noreferrer"}},[t._v("refined"),a("OutboundLink")],1),t._v("'s "),a("code",[t._v("NonEmptyString")]),t._v(" reusing existing instance for "),a("code",[t._v("String")]),t._v(" (if you use "),a("code",[t._v("refined")]),t._v(", you might want to look at "),a("a",{attrs:{href:"https://github.com/niqdev/caliban-extras#caliban-refined",target:"_blank",rel:"noopener noreferrer"}},[t._v("caliban-refined"),a("OutboundLink")],1),t._v("):")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" nonEmptyStringSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" NonEmptyString"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" \n Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("stringSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("contramap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("You can also use the "),a("code",[t._v("scalarSchema")]),t._v(" helper to create your own scalar types, providing a name, an optional description, and a function from your type to a "),a("code",[t._v("ResponseValue")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ResponseValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ObjectValue\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" unitSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("scalarSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Unit"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ObjectValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Nil"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("If you are using a custom type as part of the input you also have to provide an implicit instance of "),a("code",[t._v("ArgBuilder")]),t._v(". For example here's how to do that for "),a("code",[t._v("java.time.LocalDate")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("java"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("time"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("LocalDate\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("scala"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("util"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Try\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Value\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ExecutionError\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" localDateArgBuilder"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("LocalDate"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" Value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n Try"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("LocalDate"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fold"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ex "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" Left"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"Can't parse ")]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("value")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v(' into a LocalDate"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" innerThrowable "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ex"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Right"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" other "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" Left"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"Can't build a LocalDate from input ")]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("other")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Value classes ("),a("code",[t._v("case class SomeWrapper(self: SomeType) extends AnyVal")]),t._v(") will be unwrapped by default in Scala 2 (this is not supported by Scala 3 derivation).")]),t._v(" "),a("h2",{attrs:{id:"effects"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#effects"}},[t._v("#")]),t._v(" Effects")]),t._v(" "),a("p",[t._v("Fields can return ZIO effects. This allows you to leverage all the features provided by ZIO: timeouts, retries, access to ZIO environment, memoizing, etc. An effect will be run every time a query requiring the corresponding field is executed.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" CharacterName "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CharacterName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n character"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CharacterName "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" RIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Console"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("If you don't use ZIO environment ("),a("code",[t._v("R")]),t._v(" = "),a("code",[t._v("Any")]),t._v("), there is nothing special to do to get it working.")]),t._v(" "),a("p",[t._v("If you require a ZIO environment and use Scala 2, you can't use "),a("code",[t._v("Schema.gen")]),t._v(" or the import we saw previously because they expect "),a("code",[t._v("R")]),t._v(" to be "),a("code",[t._v("Any")]),t._v(". Instead, you need to make a new object that extends "),a("code",[t._v("caliban.schema.GenericSchema[R]")]),t._v(" for your custom "),a("code",[t._v("R")]),t._v(". Then you can use "),a("code",[t._v("gen")]),t._v(" or "),a("code",[t._v("auto")]),t._v(" from that object to generate your schema.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" MyEnv "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Console \n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" customSchema "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" GenericSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("customSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if you use semi-auto generation, use this instead:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// implicit val characterSchema: Schema[MyEnv, Character] = customSchema.gen")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// implicit val queriesSchema: Schema[MyEnv, Queries] = customSchema.gen")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" queries "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("attempt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("If you require a ZIO environment and use Scala 3, things are simpler since you don't need "),a("code",[t._v("GenericSchema")]),t._v(". Just make sure to use "),a("code",[t._v("Schema.gen")]),t._v(" with the proper R type parameter.\nTo make sure Caliban uses the proper environment, you need to specify it explicitly to "),a("code",[t._v("graphQL(...)")]),t._v(", unless you already have "),a("code",[t._v("Schema")]),t._v(" instances for your root operations in scope.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" queries "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("attempt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// implicit val queriesSchema: Schema[MyEnv, Queries] = Schema.gen")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// val api = graphQL(RootResolver(queries)) // it will infer MyEnv thanks to the instance above")]),t._v("\n")])])]),a("p",[t._v("When using the "),a("code",[t._v("derives")]),t._v(" syntax in Scala 3, you need to create an object extending "),a("code",[t._v("caliban.schema.SchemaDerivation[R]")]),t._v(" and use the "),a("code",[t._v("SemiAuto")]),t._v(" method to generate the schema.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" customSchema "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" SchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("test"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" RIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" customSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SemiAuto\n")])])]),a("h2",{attrs:{id:"subscriptions"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#subscriptions"}},[t._v("#")]),t._v(" Subscriptions")]),t._v(" "),a("p",[t._v("All the fields of the subscription root case class MUST return "),a("code",[t._v("ZStream")]),t._v(" or "),a("code",[t._v("? => ZStream")]),t._v(" objects.")]),t._v(" "),a("p",[t._v("The "),a("RouterLink",{attrs:{to:"/docs/interop.html"}},[t._v("cats and monix interop modules")]),t._v(" also let you use fs2 "),a("code",[t._v("Stream")]),t._v(" and monix "),a("code",[t._v("Observable")]),t._v(" respectively.")],1),t._v(" "),a("h2",{attrs:{id:"annotations"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#annotations"}},[t._v("#")]),t._v(" Annotations")]),t._v(" "),a("p",[t._v("Caliban supports a few annotations to enrich data types:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v('@GQLName("name")')]),t._v(" allows you to specify a different name for a data type or a field.")]),t._v(" "),a("li",[a("code",[t._v('@GQLInputName("name")')]),t._v(" allows you to specify a different name for a data type used as an input (by default, the suffix "),a("code",[t._v("Input")]),t._v(" is appended to the type name).")]),t._v(" "),a("li",[a("code",[t._v('@GQLDescription("description")')]),t._v(" lets you provide a description for a data type or field. This description will be visible when your schema is introspected.")]),t._v(" "),a("li",[a("code",[t._v('@GQLDeprecated("reason")')]),t._v(" allows deprecating a field or an enum value.")]),t._v(" "),a("li",[a("code",[t._v("@GQLExcluded")]),t._v(" allows you to hide a field from the generated schema.")]),t._v(" "),a("li",[a("code",[t._v("@GQLInterface")]),t._v(" to force a sealed trait generating an interface instead of a union.")]),t._v(" "),a("li",[a("code",[t._v("@GQLDirective(directive: Directive)")]),t._v(" to add a directive to a field or type.")]),t._v(" "),a("li",[a("code",[t._v("@GQLValueType(isScalar)")]),t._v(" forces a type to behave as a value type for derivation. Meaning that caliban will ignore the outer type and take the first case class parameter as the real type. If "),a("code",[t._v("isScalar")]),t._v(" is true, it will generate a scalar named after the case class (default: false).")]),t._v(" "),a("li",[a("code",[t._v('@GQLDefault("defaultValue")')]),t._v(" allows you to specify a default value for an input field using GraphQL syntax. The default value will be visible in your schema's SDL and during introspection.")]),t._v(" "),a("li",[a("code",[t._v("@GQLOneOfInput")]),t._v(" allows you turn a sealed trait or Scala 3 enum into an "),a("code",[t._v("@oneOf")]),t._v(" input type.")])]),t._v(" "),a("h2",{attrs:{id:"java-8-time-types"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#java-8-time-types"}},[t._v("#")]),t._v(" Java 8 Time types")]),t._v(" "),a("p",[t._v("Caliban provides implicit "),a("code",[t._v("Schema")]),t._v(" types for the standard "),a("code",[t._v("java.time")]),t._v(" types, by default these will use the\nISO standard strings for serialization and deserialization. However, you can customize this behavior by using\nexplicit constructor available under the "),a("code",[t._v("ArgBuilder")]),t._v(" companion object. For instance, you can specify an "),a("code",[t._v("instantEpoch")]),t._v("\nto handle instants which are encoded using a "),a("code",[t._v("Long")]),t._v(" from the standard java epoch time (January 1st 1970 00:00:00).\nFor some time formats you can also specify a specific "),a("code",[t._v("DateTimeFormatter")]),t._v(" to handle your particular date time needs.")]),t._v(" "),a("h2",{attrs:{id:"using-features-that-are-disabled-by-default"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#using-features-that-are-disabled-by-default"}},[t._v("#")]),t._v(" Using features that are disabled by default")]),t._v(" "),a("p",[t._v("Some features of Caliban's schema derivation are disabled by default.\nTo enable them, you need to declare a custom schema derivation object like this:")]),t._v(" "),a("code-group",[a("code-block",{attrs:{title:"Scala 2",active:""}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("SchemaDerivation\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" MySchemaDerivation "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" SchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" config "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" DerivationConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// add your config overrides here")]),t._v("\n enableSemanticNonNull "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// use the custom schema derivation defined above")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schemaForMyClass"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" MySchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3 (with given)"}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("SchemaDerivation\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" MySchemaDerivation "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" SchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" config "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" DerivationConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// add your config overrides here")]),t._v("\n enableSemanticNonNull "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// use the custom schema derivation defined above")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" MySchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3 (with derives)"}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" CommonSchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Schema "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" MySchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" CommonSchemaDerivation "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" config "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" DerivationConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// add your config overrides here")]),t._v("\n enableSemanticNonNull "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" SemiAuto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("impl"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n export impl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("*\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" SemiAuto "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("inline")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" derived"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SemiAuto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" SemiAuto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("MySchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("derived"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" MySchemaDerivation "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" MySchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" MySchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SemiAuto\n")])])])])],1),t._v(" "),a("h3",{attrs:{id:"semanticnonnull-support"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#semanticnonnull-support"}},[t._v("#")]),t._v(" SemanticNonNull support")]),t._v(" "),a("p",[t._v("Caliban supports deriving schemas to the form that supports "),a("a",{attrs:{href:"https://github.com/graphql/graphql-spec/pull/1065",target:"_blank",rel:"noopener noreferrer"}},[t._v("the SemanticNonNull type RFC"),a("OutboundLink")],1),t._v(", by introducing the "),a("code",[t._v("@semanticNonNull")]),t._v(" directive.\nWhile Caliban resolves all fallible effectful types ("),a("code",[t._v("ZIO[R, Throwable, A]")]),t._v(", ...) as nullable by default,\nwith the feature enabled, fields that don't get resolved to nullable types (for example, "),a("code",[t._v("ZIO[R, Throwable, A]")]),t._v(" where "),a("code",[t._v("A")]),t._v(" is not "),a("code",[t._v("Option[A]")]),t._v(", ...)\nwill be marked with "),a("code",[t._v("@semanticNonNull")]),t._v(" to express that the field never returns "),a("code",[t._v("null")]),t._v(" unless the effect fails.\n"),a("code",[t._v("@GQLNullable")]),t._v(" annotation can be used to override this behavior per field.")]),t._v(" "),a("p",[t._v("If you have custom types that override the "),a("code",[t._v("Schema")]),t._v(" trait, make sure to override "),a("code",[t._v("nullable")]),t._v(" and "),a("code",[t._v("canFail")]),t._v(" methods to return the correct values.\nAll types that return "),a("code",[t._v("false")]),t._v(" for "),a("code",[t._v("nullable")]),t._v(" and "),a("code",[t._v("true")]),t._v(" for "),a("code",[t._v("canFail")]),t._v(" will be treated as semantically non-nullable.")]),t._v(" "),a("h2",{attrs:{id:"building-schemas-by-hand"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#building-schemas-by-hand"}},[t._v("#")]),t._v(" Building Schemas by hand")]),t._v(" "),a("p",[t._v("Sometimes for whatever reason schema generation fails. This can happen if your schema has co-recursive types and derivation is unable\nto generate a schema for them. In cases like these you may need to instead create your own schema by hand.")]),t._v(" "),a("p",[t._v("Consider the case where you have three types which create cyclical dependencies on one another")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("UIO\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" users"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("User"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" parent"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" organization"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Organization"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Organization"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" groups"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" User"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" group"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("These three types all depend on one another and if you attempt to generate a schema from them you will either end up with compiler errors or you will end up with a nasty runtime\nerror from a "),a("code",[t._v("NullPointerException")]),t._v(". To help the compiler out we can hand generate the types for these case classes instead.")]),t._v(" "),a("code-group",[a("code-block",{attrs:{title:"Scala 2",active:""}},[a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("obj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" groupSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" obj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Group"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"A group of users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" ft "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("users"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"parent"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parent"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"organization"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("organization"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" orgSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Organization"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" obj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Organization"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"An organization of groups"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" ft "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"groups"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("groups"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" userSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" User"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" obj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"User"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"A user of the service"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" ft "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"group"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3"}},[a("div",{staticClass:"language-scala 3 mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("customObj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" customObj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Group"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"A group of users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("users"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"parent"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parent"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"organization"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("organization"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Organization"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" customObj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Organization"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"An organization of groups"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"groups"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("groups"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" User"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" customObj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"User"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"A user of the service"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"group"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])],1),t._v(" "),a("h2",{attrs:{id:"schema-transformations"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#schema-transformations"}},[t._v("#")]),t._v(" Schema transformations")]),t._v(" "),a("p",[t._v("It is also possible to modify your schemas after they have been generated.\nThis can be useful if you want to rename or remove particular types, fields or arguments from your schema without modifying the related Scala types.")]),t._v(" "),a("p",[t._v("For that, simply use the "),a("code",[t._v("GraphQL#transform")]),t._v(" method and provide one of the possible transformers:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("RenameType")]),t._v(" to rename types (providing a list of "),a("code",[t._v("(OldName -> NewName)")]),t._v(")")]),t._v(" "),a("li",[a("code",[t._v("RenameField")]),t._v(" to rename a field (providing a list of "),a("code",[t._v("(TypeName -> oldName -> newName)")]),t._v(")")]),t._v(" "),a("li",[a("code",[t._v("RenameArgument")]),t._v(" to rename an argument (providing a list of "),a("code",[t._v("(TypeName -> fieldName -> oldArgumentName -> newArgumentName)")]),t._v(")")]),t._v(" "),a("li",[a("code",[t._v("ExcludeField")]),t._v(" to exclude a field (providing a list of "),a("code",[t._v("(TypeName -> fieldToBeExcluded)")]),t._v(")")]),t._v(" "),a("li",[a("code",[t._v("ExcludeInputField")]),t._v(" to exclude an input field (providing a list of "),a("code",[t._v("(TypeName -> fieldToBeExcluded)")]),t._v(")")]),t._v(" "),a("li",[a("code",[t._v("ExcludeArgument")]),t._v(" to exclude an argument (providing a list of "),a("code",[t._v("(TypeName -> fieldName -> argumentToBeExcluded)")]),t._v(")")]),t._v(" "),a("li",[a("code",[t._v("ExcludeDirectives")]),t._v(" to exclude fields and input fields annotated with a specific directive (providing a list of "),a("code",[t._v("GQLDirective")]),t._v(" or a "),a("code",[t._v("Directive => Boolean")]),t._v(" predicate)")])]),t._v(" "),a("p",[t._v("In the following example, we can expose 2 different APIs created from the same schema: the v1 API will not expose the "),a("code",[t._v("nicknames")]),t._v(" field of the "),a("code",[t._v("Character")]),t._v(" type.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Beta"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" GQLDirective"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"beta"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("character"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@Beta")]),t._v(" nicknames"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" apiBeta "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" apiV1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" apiBeta"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("transform"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Transformer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ExcludeDirectives"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Beta"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// alternatively:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// val apiV1 = apiBeta.transform(Transformer.ExcludeField("Character" -> "nicknames"))')]),t._v("\n")])])]),a("p",[t._v("You can also create your own transformers by extending the "),a("code",[t._v("Transformer")]),t._v(" trait and implementing its methods.")])],1)}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[37],{321:function(t,a,s){"use strict";s.r(a);var e=s(14),n=Object(e.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"schema-generation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#schema-generation"}},[t._v("#")]),t._v(" Schema generation")]),t._v(" "),a("p",[t._v("A GraphQL schema will be derived automatically at compile-time (no reflection) from the types present in your resolver.")]),t._v(" "),a("p",[t._v("If you're more interested in the schema-first approach, it is also possible to "),a("RouterLink",{attrs:{to:"/docs/server-codegen.html"}},[t._v("generate the Scala code from a GraphQL schema file")]),t._v(".")],1),t._v(" "),a("p",[t._v("The table below shows how common Scala types are converted to GraphQL types.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Scala Type")]),t._v(" "),a("th",[t._v("GraphQL Type")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[t._v("Boolean")]),t._v(" "),a("td",[t._v("Boolean")])]),t._v(" "),a("tr",[a("td",[t._v("Int")]),t._v(" "),a("td",[t._v("Int")])]),t._v(" "),a("tr",[a("td",[t._v("Float")]),t._v(" "),a("td",[t._v("Float")])]),t._v(" "),a("tr",[a("td",[t._v("Double")]),t._v(" "),a("td",[t._v("Float")])]),t._v(" "),a("tr",[a("td",[t._v("String")]),t._v(" "),a("td",[t._v("String")])]),t._v(" "),a("tr",[a("td",[t._v("java.util.UUID")]),t._v(" "),a("td",[t._v("ID")])]),t._v(" "),a("tr",[a("td",[t._v("Unit")]),t._v(" "),a("td",[t._v("Unit (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("Long")]),t._v(" "),a("td",[t._v("Long (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("BigInt")]),t._v(" "),a("td",[t._v("BigInt (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("BigDecimal")]),t._v(" "),a("td",[t._v("BigDecimal (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.Instant")]),t._v(" "),a("td",[t._v("Instant (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.LocalDate")]),t._v(" "),a("td",[t._v("LocalDate (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.LocalTime")]),t._v(" "),a("td",[t._v("LocalTime (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.LocalDateTime")]),t._v(" "),a("td",[t._v("LocalDateTime (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.OffsetDateTime")]),t._v(" "),a("td",[t._v("OffsetDateTime (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.ZonedDateTime")]),t._v(" "),a("td",[t._v("ZonedDateTime (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("Case Class")]),t._v(" "),a("td",[t._v("Object")])]),t._v(" "),a("tr",[a("td",[t._v("Sealed Trait")]),t._v(" "),a("td",[t._v("Enum, Union or Interface (see "),a("a",{attrs:{href:"#enums-unions-interfaces"}},[t._v("below")]),t._v(")")])]),t._v(" "),a("tr",[a("td",[t._v("Option[A]")]),t._v(" "),a("td",[t._v("Nullable A")])]),t._v(" "),a("tr",[a("td",[t._v("List[A]")]),t._v(" "),a("td",[t._v("List of A")])]),t._v(" "),a("tr",[a("td",[t._v("Set[A]")]),t._v(" "),a("td",[t._v("List of A")])]),t._v(" "),a("tr",[a("td",[t._v("Seq[A]")]),t._v(" "),a("td",[t._v("List of A")])]),t._v(" "),a("tr",[a("td",[t._v("Vector[A]")]),t._v(" "),a("td",[t._v("List of A")])]),t._v(" "),a("tr",[a("td",[t._v("A => B")]),t._v(" "),a("td",[t._v("A and B")])]),t._v(" "),a("tr",[a("td",[t._v("(A, B)")]),t._v(" "),a("td",[t._v("Object with 2 fields "),a("code",[t._v("_1")]),t._v(" and "),a("code",[t._v("_2")])])]),t._v(" "),a("tr",[a("td",[t._v("Either[A, B]")]),t._v(" "),a("td",[t._v("Object with 2 nullable fields "),a("code",[t._v("left")]),t._v(" and "),a("code",[t._v("right")])])]),t._v(" "),a("tr",[a("td",[t._v("Map[A, B]")]),t._v(" "),a("td",[t._v("List of Object with 2 fields "),a("code",[t._v("key")]),t._v(" and "),a("code",[t._v("value")])])]),t._v(" "),a("tr",[a("td",[t._v("ZIO[R, Nothing, A]")]),t._v(" "),a("td",[t._v("A")])]),t._v(" "),a("tr",[a("td",[t._v("ZIO[R, Throwable, A]")]),t._v(" "),a("td",[t._v("Nullable A")])]),t._v(" "),a("tr",[a("td",[t._v("Future[A]")]),t._v(" "),a("td",[t._v("Nullable A")])]),t._v(" "),a("tr",[a("td",[t._v("ZStream[R, Throwable, A]")]),t._v(" "),a("td",[t._v("A (subscription) or List of A (query, mutation)")])]),t._v(" "),a("tr",[a("td",[t._v("Json (from "),a("a",{attrs:{href:"https://github.com/circe/circe",target:"_blank",rel:"noopener noreferrer"}},[t._v("Circe"),a("OutboundLink")],1),t._v(")")]),t._v(" "),a("td",[t._v("Json (custom scalar, need "),a("code",[t._v("import caliban.interop.circe.json._")]),t._v(")")])]),t._v(" "),a("tr",[a("td",[t._v("Json (from "),a("a",{attrs:{href:"https://github.com/playframework/play-json",target:"_blank",rel:"noopener noreferrer"}},[t._v("play-json"),a("OutboundLink")],1),t._v(")")]),t._v(" "),a("td",[t._v("Json (custom scalar, need "),a("code",[t._v("import caliban.interop.play.json._")]),t._v(")")])])])]),t._v(" "),a("p",[t._v("See the "),a("a",{attrs:{href:"#custom-types"}},[t._v("Custom Types")]),t._v(" section to find out how to support your own types.")]),t._v(" "),a("p",[t._v("If you want Caliban to support other standard types, feel free to "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/issues",target:"_blank",rel:"noopener noreferrer"}},[t._v("file an issue"),a("OutboundLink")],1),t._v(" or even a PR.")]),t._v(" "),a("h2",{attrs:{id:"enums-unions-interfaces"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#enums-unions-interfaces"}},[t._v("#")]),t._v(" Enums, unions, interfaces")]),t._v(" "),a("p",[t._v("A sealed trait will be converted to a different GraphQL type depending on its content:")]),t._v(" "),a("ul",[a("li",[t._v("a sealed trait with only case objects will be converted to an "),a("code",[t._v("ENUM")])]),t._v(" "),a("li",[t._v("a sealed trait with only case classes will be converted to a "),a("code",[t._v("UNION")])])]),t._v(" "),a("p",[t._v('GraphQL does not support empty objects, so in case a sealed trait mixes case classes and case objects, a union type will be created and the case objects will have a "fake" field named '),a("code",[t._v("_")]),t._v(" which is not queryable.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Origin\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Origin "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" EARTH "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" MARS "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" BELT "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("The snippet above will produce the following GraphQL type:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("enum")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("BELT")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("EARTH")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("MARS")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Here's an example of union:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Role\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Role "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Captain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("shipName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Engineer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("specialty"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Mechanic "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("The snippet above will produce the following GraphQL type:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("union")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Role")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Captain")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Engineer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Mechanic")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Captain")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("shipName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Engineer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("specialty")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mechanic")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("Boolean")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("If your type needs to be shared between multiple unions you can use the "),a("code",[t._v("@GQLValueType")]),t._v(" annotation to have caliban\nproxy to another type beyond the sealed trait.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Pilot"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("callSign"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Role\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Role "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Captain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("shipName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Engineer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("specialty"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLValueType")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Proxy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("pilot"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Pilot"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("This will produce the following GraphQL Types:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("union")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Role")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Captain")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Engineer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Pilot")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Captain")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("shipName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Engineer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("specialty")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Pilot")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("callSign")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("If you prefer an "),a("code",[t._v("Interface")]),t._v(" instead of a "),a("code",[t._v("Union")]),t._v(" type, add the "),a("code",[t._v("@GQLInterface")]),t._v(" annotation to your sealed trait.\nAn interface will be created with all the fields that are common to the case classes extending the sealed trait, as long as they return the same type.")]),t._v(" "),a("p",[t._v("If you prefer to have a "),a("code",[t._v("Union")]),t._v(" type instead of an "),a("code",[t._v("Enum")]),t._v(", even when the sealed trait contains only objects, add the "),a("code",[t._v("@GQLUnion")]),t._v(" annotation.")]),t._v(" "),a("h2",{attrs:{id:"case-classes-and-sealed-traits"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#case-classes-and-sealed-traits"}},[t._v("#")]),t._v(" Case classes and sealed traits")]),t._v(" "),a("p",[t._v("The transformation between Scala types and GraphQL types is handled by a typeclass named "),a("code",[t._v("Schema")]),t._v(". As mentioned earlier, Caliban provides instances of "),a("code",[t._v("Schema")]),t._v(" for all basic Scala types, but inevitably you will need to support your own types, in particular case classes and sealed traits.")]),t._v(" "),a("p",[t._v("Caliban is able to generate instances of "),a("code",[t._v("Schema")]),t._v(" for case classes and sealed traits. You have two choices for doing that: auto derivation and semi-auto derivation.")]),t._v(" "),a("h3",{attrs:{id:"auto-derivation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#auto-derivation"}},[t._v("#")]),t._v(" Auto derivation")]),t._v(" "),a("p",[t._v("Auto derivation is achieved easily by adding the following import:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n")])])]),a("p",[t._v("Using this import, Caliban will generate "),a("code",[t._v("Schema")]),t._v(" instances for all the case classes and sealed traits that are found inside your resolver.")]),t._v(" "),a("div",{staticClass:"custom-block warning"},[a("p",{staticClass:"custom-block-title"},[t._v("Limitations")]),t._v(" "),a("p",[t._v("Auto derivation is the easiest way to get started, but it has some drawbacks:")]),t._v(" "),a("ul",[a("li",[t._v("If a type is referenced in several places inside your resolver, a "),a("code",[t._v("Schema")]),t._v(" will be generated for each occurrence, which can lead to longer compilation times and a high amount of generated code (a sign of this is that the compiler will suggest increasing "),a("code",[t._v("-Xmax-inlines")]),t._v(" in Scala 3).")]),t._v(" "),a("li",[t._v("When a "),a("code",[t._v("Schema")]),t._v(" is missing for a nested type inside your resolver, it can sometimes be difficult to find out which type is missing when using auto derivation, because the error message will mention the root type and not the nested one.")]),t._v(" "),a("li",[t._v("The macro that generates the "),a("code",[t._v("Schema")]),t._v(" instances sometimes gets confused when there are a lot of nested or recursive types, and can mistakenly generate a "),a("code",[t._v("Schema")]),t._v(" for types that already have a "),a("code",[t._v("Schema")]),t._v(" in scope. For this reason, semi-auto derivation is recommended for non-trivial schemas.")])])]),t._v(" "),a("h3",{attrs:{id:"semi-auto-derivation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#semi-auto-derivation"}},[t._v("#")]),t._v(" Semi-auto derivation")]),t._v(" "),a("p",[t._v("Semi-auto derivation is achieved as follows for each type that needs a "),a("code",[t._v("Schema")]),t._v(" instance ("),a("code",[t._v("MyClass")]),t._v(" in the example):")]),t._v(" "),a("code-group",[a("code-block",{attrs:{title:"Scala 2",active:""}},[a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schemaForMyClass"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3"}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SemiAuto\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if you don't want to use the `derives` syntax, you can also use the following:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])])])],1),t._v(" "),a("p",[t._v("In Scala 3, derivation doesn't support value classes and opaque types. You can use "),a("code",[t._v("Schema.genDebug")]),t._v(" to print the generated code in the console.")]),t._v(" "),a("h3",{attrs:{id:"combining-auto-and-semi-auto-derivation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#combining-auto-and-semi-auto-derivation"}},[t._v("#")]),t._v(" Combining auto and semi-auto derivation")]),t._v(" "),a("p",[t._v("For some types such as enums, it might be desirable to use auto derivation to reduce boilerplate schema definitions:")]),t._v(" "),a("code-group",[a("code-block",{attrs:{title:"Scala 2",active:""}},[a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Origin\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Origin "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" EARTH "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" MARS "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" BELT "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schemaForMyClass"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3 (Any schema)"}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("enum")]),t._v(" Origin "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Auto "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" EARTH"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MARS"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" BELT\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if you don't want to use the `derives` syntax, you can also use the following:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("derived\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3 (Custom schema)"}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("SchemaDerivation\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" MyEnv\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" EnvSchema "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" SchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("enum")]),t._v(" Origin "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" EnvSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Auto "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" EARTH"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MARS"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" BELT\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if you don't want to use the `derives` syntax:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" EnvSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("derived\n")])])])])],1),t._v(" "),a("h3",{attrs:{id:"deriving-fields-from-case-class-methods-scala-3-only"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#deriving-fields-from-case-class-methods-scala-3-only"}},[t._v("#")]),t._v(" Deriving fields from case class methods (Scala 3 only)")]),t._v(" "),a("p",[t._v("In certain cases, your type might contain fields whose value depends on other fields. For example, you might have a "),a("code",[t._v("Person")]),t._v(" type with a "),a("code",[t._v("fullName")]),t._v(" field that is derived from the "),a("code",[t._v("firstName")]),t._v(" and "),a("code",[t._v("lastName")]),t._v(" fields. In this case, you can use the "),a("code",[t._v("@GQLField")]),t._v(" annotation to indicate that the field should be derived from the method with the same name.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Annotations"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("GQLField\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Person"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n firstName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n lastName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SemiAuto "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLField")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" fullName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("firstName")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v(" ")]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("lastName")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("This case class will generate the following GraphQL type:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Person")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("firstName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("lastName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("fullName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("The methods annotated with "),a("code",[t._v("@GQLField")]),t._v(" can return any type for which a "),a("code",[t._v("Schema")]),t._v(" is defined for, including effects such as "),a("code",[t._v("ZIO")]),t._v(" and "),a("code",[t._v("ZQuery")]),t._v(".\nIn addition, you can use any other annotation that is supported for case class arguments, such as "),a("code",[t._v("@GQLName")]),t._v(", "),a("code",[t._v("@GQLDescription")]),t._v(" and "),a("code",[t._v("@GQLDeprecated")]),t._v(".")]),t._v(" "),a("p",[t._v("To reduce boilerplate of annotating a lot of methods with "),a("code",[t._v("@GQLField")]),t._v(", Caliban also provides the "),a("code",[t._v("@GQLFieldsFromMethods")]),t._v(" annotation that can be used to derive fields from all methods in a case class / case object.")]),t._v(" "),a("p",[t._v("For demonstration purposes (only!), the example above can be rewritten as follows:")]),t._v(" "),a("div",{staticClass:"language-scala 3 extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Annotations"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("GQLFieldsFromMethods\n\n"),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLFieldsFromMethods")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Person"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n fullName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SemiAuto "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" split "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" fullName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("split"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('" "')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" firstName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" split"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("head\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" lastName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" split"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("last\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[t._v("Annotate a public method with "),a("code",[t._v("@GQLExcluded")]),t._v(" to exclude it from field derivation.")])]),t._v(" "),a("div",{staticClass:"custom-block warning"},[a("p",{staticClass:"custom-block-title"},[t._v("Caveats")]),t._v(" "),a("p",[t._v("Derivation of fields via the "),a("code",[t._v("@GQLField")]),t._v(" / "),a("code",[t._v("@GQLFieldsFromMethods")]),t._v(" annotation can be convenient in certain cases, but has the following limitations:")]),t._v(" "),a("ul",[a("li",[t._v("The method cannot take arguments. If you need to derive a field that requires arguments, you can return a function instead.")]),t._v(" "),a("li",[t._v("The method must be public (i.e. not "),a("code",[t._v("private")]),t._v(" or "),a("code",[t._v("protected")]),t._v(").")]),t._v(" "),a("li",[t._v("It currently only works with methods (i.e., "),a("code",[t._v("def")]),t._v("). If you need to cache the output of the method, you can create a private lazy val and return it from the method.")]),t._v(" "),a("li",[t._v("It is not compatible with ahead-of-time compilation (e.g., generating a GraalVM native-image executable).")])])]),t._v(" "),a("h2",{attrs:{id:"arguments"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#arguments"}},[t._v("#")]),t._v(" Arguments")]),t._v(" "),a("p",[t._v("To declare a field that take arguments, create a dedicated case class representing the arguments and make the field a "),a("em",[t._v("function")]),t._v(" from this class to the result type.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" origin"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" FilterArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("origin"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FilterArgs "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("The snippet above will produce the following GraphQL type:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Queries")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("characters")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("origin")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Caliban provides auto-derivation for common types such as "),a("code",[t._v("Int")]),t._v(", "),a("code",[t._v("String")]),t._v(", "),a("code",[t._v("List")]),t._v(", "),a("code",[t._v("Option")]),t._v(", etc. but you can also support your own types by providing an implicit instance of "),a("code",[t._v("ArgBuilder")]),t._v(" that defines how incoming arguments from that types should be extracted. You also need a "),a("code",[t._v("Schema")]),t._v(" for those types.")]),t._v(" "),a("p",[t._v("Derivation of "),a("code",[t._v("ArgBuilder")]),t._v(" for case classes works similarly to "),a("code",[t._v("Schema")]),t._v(" derivation. You can use auto derivation by adding the following import:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n")])])]),a("p",[t._v("Or you can use semi-auto derivation as follows:")]),t._v(" "),a("code-group",[a("code-block",{attrs:{title:"Scala 2",active:""}},[a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" argBuilderForMyClass"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schemaForMyClass"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3"}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SemiAuto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ArgBuilder\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if you don't want to use the `derives` syntax, you can also use the following:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])])])],1),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[t._v("There is no "),a("code",[t._v("ArgBuilder")]),t._v(" for tuples. If you have multiple arguments, use a case class containing all of them instead of a tuple.")])]),t._v(" "),a("h3",{attrs:{id:"input-objects"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#input-objects"}},[t._v("#")]),t._v(" Input objects")]),t._v(" "),a("p",[t._v("GraphQL input objects can be derived from case classes in the same way as arguments")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("firstName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" lastName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" NameArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("author"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" NameArgs "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("This will generate the following schema:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("input")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token atom-input class-name"}},[t._v("NameInput")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("firstName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("lastName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Queries")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("author")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token atom-input class-name"}},[t._v("NameInput")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h3",{attrs:{id:"oneof-input-objects"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#oneof-input-objects"}},[t._v("#")]),t._v(" "),a("code",[t._v("@oneOf")]),t._v(" input objects")]),t._v(" "),a("p",[t._v("A "),a("code",[t._v("@oneOf")]),t._v(" input object is a special type of input object, in which only one of its fields must be set by the client. It is especially useful when you want a user to be able to choose between several potential input types.\nThis feature is still an RFC and therefore not yet officially part of the GraphQL spec, but Caliban supports it!")]),t._v(" "),a("p",[t._v("To define a "),a("code",[t._v("@oneOf")]),t._v(" input object, you need to create a sealed trait (or an enum in Scala 3) with case classes that extend it. The case classes must have a single field, which is the field that the client can set. The sealed trait / enum must be annotated with "),a("code",[t._v("@GQLOneOfInput")]),t._v(".")]),t._v(" "),a("code-group",[a("code-block",{attrs:{title:"Sealed trait",active:""}},[a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Annotations"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("GQLOneOfInput\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("firstName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" lastName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLOneOfInput")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" AuthorInput\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" AuthorInput "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" ById"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" ByName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" AuthorArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lookup"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" AuthorInput"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("author"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" AuthorArgs "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Enum (Scala 3)"}},[a("div",{staticClass:"language-scala 3 mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Annotations"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("GQLOneOfInput\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("firstName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" lastName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLOneOfInput")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("enum")]),t._v(" AuthorInput "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" ById"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" ByName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" AuthorArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lookup"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" AuthorInput"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("author"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" AuthorArgs "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])],1),t._v(" "),a("p",[t._v("This will generate the following schema, and the validation will verify that only one of those fields is provided in incoming queries.")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("input")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token atom-input class-name"}},[t._v("NameInput")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("firstName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("lastName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("input")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token atom-input class-name"}},[t._v("AuthorInput")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@oneOf")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("id")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token atom-input class-name"}},[t._v("NameInput")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Queries")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("author")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("lookup")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token atom-input class-name"}},[t._v("AuthorInput")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("A few things to keep in mind when using "),a("code",[t._v("@oneOf")]),t._v(" input objects:")]),t._v(" "),a("ul",[a("li",[t._v("The leaf case classes must contain "),a("strong",[t._v("exactly 1 non-nullable field")]),t._v(". If you need more than one field, you should wrap them in a case class.")]),t._v(" "),a("li",[t._v("The field names in the leaf cases must be unique.")]),t._v(" "),a("li",[t._v("You must have a "),a("code",[t._v("Schema")]),t._v(" and an "),a("code",[t._v("ArgBuilder")]),t._v(" for any objects used in the leaf cases.")])]),t._v(" "),a("h2",{attrs:{id:"custom-types"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#custom-types"}},[t._v("#")]),t._v(" Custom types")]),t._v(" "),a("p",[t._v("Caliban provides auto-derivation for common types such as "),a("code",[t._v("Int")]),t._v(", "),a("code",[t._v("String")]),t._v(", "),a("code",[t._v("List")]),t._v(", "),a("code",[t._v("Option")]),t._v(", etc. but you can also support your own types by providing an implicit instance of "),a("code",[t._v("Schema")]),t._v(". Note that you don't have to do this if your types are just case classes composed of common types.")]),t._v(" "),a("p",[t._v("An easy way to do this is to reuse existing instances and use "),a("code",[t._v("contramap")]),t._v(" to map from your type to the original type. Here's an example of creating an instance for "),a("a",{attrs:{href:"https://github.com/fthomas/refined",target:"_blank",rel:"noopener noreferrer"}},[t._v("refined"),a("OutboundLink")],1),t._v("'s "),a("code",[t._v("NonEmptyString")]),t._v(" reusing existing instance for "),a("code",[t._v("String")]),t._v(" (if you use "),a("code",[t._v("refined")]),t._v(", you might want to look at "),a("a",{attrs:{href:"https://github.com/niqdev/caliban-extras#caliban-refined",target:"_blank",rel:"noopener noreferrer"}},[t._v("caliban-refined"),a("OutboundLink")],1),t._v("):")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" nonEmptyStringSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" NonEmptyString"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" \n Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("stringSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("contramap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("You can also use the "),a("code",[t._v("scalarSchema")]),t._v(" helper to create your own scalar types, providing a name, an optional description, and a function from your type to a "),a("code",[t._v("ResponseValue")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ResponseValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ObjectValue\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" unitSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("scalarSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Unit"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ObjectValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Nil"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("If you are using a custom type as part of the input you also have to provide an implicit instance of "),a("code",[t._v("ArgBuilder")]),t._v(". For example here's how to do that for "),a("code",[t._v("java.time.LocalDate")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("java"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("time"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("LocalDate\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("scala"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("util"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Try\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Value\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ExecutionError\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" localDateArgBuilder"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("LocalDate"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" Value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n Try"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("LocalDate"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fold"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ex "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" Left"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"Can't parse ")]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("value")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v(' into a LocalDate"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" innerThrowable "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ex"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Right"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" other "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" Left"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"Can't build a LocalDate from input ")]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("other")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Value classes ("),a("code",[t._v("case class SomeWrapper(self: SomeType) extends AnyVal")]),t._v(") will be unwrapped by default in Scala 2 (this is not supported by Scala 3 derivation).")]),t._v(" "),a("h2",{attrs:{id:"effects"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#effects"}},[t._v("#")]),t._v(" Effects")]),t._v(" "),a("p",[t._v("Fields can return ZIO effects. This allows you to leverage all the features provided by ZIO: timeouts, retries, access to ZIO environment, memoizing, etc. An effect will be run every time a query requiring the corresponding field is executed.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" CharacterName "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CharacterName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n character"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CharacterName "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" RIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Console"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("If you don't use ZIO environment ("),a("code",[t._v("R")]),t._v(" = "),a("code",[t._v("Any")]),t._v("), there is nothing special to do to get it working.")]),t._v(" "),a("p",[t._v("If you require a ZIO environment and use Scala 2, you can't use "),a("code",[t._v("Schema.gen")]),t._v(" or the import we saw previously because they expect "),a("code",[t._v("R")]),t._v(" to be "),a("code",[t._v("Any")]),t._v(". Instead, you need to make a new object that extends "),a("code",[t._v("caliban.schema.GenericSchema[R]")]),t._v(" for your custom "),a("code",[t._v("R")]),t._v(". Then you can use "),a("code",[t._v("gen")]),t._v(" or "),a("code",[t._v("auto")]),t._v(" from that object to generate your schema.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" MyEnv "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Console \n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" customSchema "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" GenericSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("customSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if you use semi-auto generation, use this instead:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// implicit val characterSchema: Schema[MyEnv, Character] = customSchema.gen")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// implicit val queriesSchema: Schema[MyEnv, Queries] = customSchema.gen")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" queries "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("attempt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("If you require a ZIO environment and use Scala 3, things are simpler since you don't need "),a("code",[t._v("GenericSchema")]),t._v(". Just make sure to use "),a("code",[t._v("Schema.gen")]),t._v(" with the proper R type parameter.\nTo make sure Caliban uses the proper environment, you need to specify it explicitly to "),a("code",[t._v("graphQL(...)")]),t._v(", unless you already have "),a("code",[t._v("Schema")]),t._v(" instances for your root operations in scope.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" queries "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("attempt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// implicit val queriesSchema: Schema[MyEnv, Queries] = Schema.gen")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// val api = graphQL(RootResolver(queries)) // it will infer MyEnv thanks to the instance above")]),t._v("\n")])])]),a("p",[t._v("When using the "),a("code",[t._v("derives")]),t._v(" syntax in Scala 3, you need to create an object extending "),a("code",[t._v("caliban.schema.SchemaDerivation[R]")]),t._v(" and use the "),a("code",[t._v("SemiAuto")]),t._v(" method to generate the schema.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" customSchema "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" SchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("test"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" RIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" customSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SemiAuto\n")])])]),a("h2",{attrs:{id:"subscriptions"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#subscriptions"}},[t._v("#")]),t._v(" Subscriptions")]),t._v(" "),a("p",[t._v("All the fields of the subscription root case class MUST return "),a("code",[t._v("ZStream")]),t._v(" or "),a("code",[t._v("? => ZStream")]),t._v(" objects.")]),t._v(" "),a("p",[t._v("The "),a("RouterLink",{attrs:{to:"/docs/interop.html"}},[t._v("cats and monix interop modules")]),t._v(" also let you use fs2 "),a("code",[t._v("Stream")]),t._v(" and monix "),a("code",[t._v("Observable")]),t._v(" respectively.")],1),t._v(" "),a("h2",{attrs:{id:"annotations"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#annotations"}},[t._v("#")]),t._v(" Annotations")]),t._v(" "),a("p",[t._v("Caliban supports a few annotations to enrich data types:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v('@GQLName("name")')]),t._v(" allows you to specify a different name for a data type or a field.")]),t._v(" "),a("li",[a("code",[t._v('@GQLInputName("name")')]),t._v(" allows you to specify a different name for a data type used as an input (by default, the suffix "),a("code",[t._v("Input")]),t._v(" is appended to the type name).")]),t._v(" "),a("li",[a("code",[t._v('@GQLDescription("description")')]),t._v(" lets you provide a description for a data type or field. This description will be visible when your schema is introspected.")]),t._v(" "),a("li",[a("code",[t._v('@GQLDeprecated("reason")')]),t._v(" allows deprecating a field or an enum value.")]),t._v(" "),a("li",[a("code",[t._v("@GQLExcluded")]),t._v(" allows you to hide a field from the generated schema.")]),t._v(" "),a("li",[a("code",[t._v("@GQLInterface")]),t._v(" to force a sealed trait generating an interface instead of a union.")]),t._v(" "),a("li",[a("code",[t._v("@GQLDirective(directive: Directive)")]),t._v(" to add a directive to a field or type.")]),t._v(" "),a("li",[a("code",[t._v("@GQLValueType(isScalar)")]),t._v(" forces a type to behave as a value type for derivation. Meaning that caliban will ignore the outer type and take the first case class parameter as the real type. If "),a("code",[t._v("isScalar")]),t._v(" is true, it will generate a scalar named after the case class (default: false).")]),t._v(" "),a("li",[a("code",[t._v('@GQLDefault("defaultValue")')]),t._v(" allows you to specify a default value for an input field using GraphQL syntax. The default value will be visible in your schema's SDL and during introspection.")]),t._v(" "),a("li",[a("code",[t._v("@GQLOneOfInput")]),t._v(" allows you turn a sealed trait or Scala 3 enum into an "),a("code",[t._v("@oneOf")]),t._v(" input type.")])]),t._v(" "),a("h2",{attrs:{id:"java-8-time-types"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#java-8-time-types"}},[t._v("#")]),t._v(" Java 8 Time types")]),t._v(" "),a("p",[t._v("Caliban provides implicit "),a("code",[t._v("Schema")]),t._v(" types for the standard "),a("code",[t._v("java.time")]),t._v(" types, by default these will use the\nISO standard strings for serialization and deserialization. However, you can customize this behavior by using\nexplicit constructor available under the "),a("code",[t._v("ArgBuilder")]),t._v(" companion object. For instance, you can specify an "),a("code",[t._v("instantEpoch")]),t._v("\nto handle instants which are encoded using a "),a("code",[t._v("Long")]),t._v(" from the standard java epoch time (January 1st 1970 00:00:00).\nFor some time formats you can also specify a specific "),a("code",[t._v("DateTimeFormatter")]),t._v(" to handle your particular date time needs.")]),t._v(" "),a("h2",{attrs:{id:"using-features-that-are-disabled-by-default"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#using-features-that-are-disabled-by-default"}},[t._v("#")]),t._v(" Using features that are disabled by default")]),t._v(" "),a("p",[t._v("Some features of Caliban's schema derivation are disabled by default.\nTo enable them, you need to declare a custom schema derivation object like this:")]),t._v(" "),a("code-group",[a("code-block",{attrs:{title:"Scala 2",active:""}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("SchemaDerivation\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" MySchemaDerivation "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" SchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" config "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" DerivationConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// add your config overrides here")]),t._v("\n enableSemanticNonNull "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// use the custom schema derivation defined above")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schemaForMyClass"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" MySchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3 (with given)"}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("SchemaDerivation\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" MySchemaDerivation "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" SchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" config "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" DerivationConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// add your config overrides here")]),t._v("\n enableSemanticNonNull "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// use the custom schema derivation defined above")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" MySchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3 (with derives)"}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" CommonSchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Schema "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" MySchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" CommonSchemaDerivation "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" config "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" DerivationConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// add your config overrides here")]),t._v("\n enableSemanticNonNull "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" SemiAuto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("impl"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n export impl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("*\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" SemiAuto "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("inline")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" derived"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SemiAuto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" SemiAuto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("MySchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("derived"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" MySchemaDerivation "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" MySchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" MySchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SemiAuto\n")])])])])],1),t._v(" "),a("h3",{attrs:{id:"semanticnonnull-support"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#semanticnonnull-support"}},[t._v("#")]),t._v(" SemanticNonNull support")]),t._v(" "),a("p",[t._v("Caliban supports deriving schemas to the form that supports "),a("a",{attrs:{href:"https://github.com/graphql/graphql-spec/pull/1065",target:"_blank",rel:"noopener noreferrer"}},[t._v("the SemanticNonNull type RFC"),a("OutboundLink")],1),t._v(", by introducing the "),a("code",[t._v("@semanticNonNull")]),t._v(" directive.\nWhile Caliban resolves all fallible effectful types ("),a("code",[t._v("ZIO[R, Throwable, A]")]),t._v(", ...) as nullable by default,\nwith the feature enabled, fields that don't get resolved to nullable types (for example, "),a("code",[t._v("ZIO[R, Throwable, A]")]),t._v(" where "),a("code",[t._v("A")]),t._v(" is not "),a("code",[t._v("Option[A]")]),t._v(", ...)\nwill be marked with "),a("code",[t._v("@semanticNonNull")]),t._v(" to express that the field never returns "),a("code",[t._v("null")]),t._v(" unless the effect fails.\n"),a("code",[t._v("@GQLNullable")]),t._v(" annotation can be used to override this behavior per field.")]),t._v(" "),a("p",[t._v("If you have custom types that override the "),a("code",[t._v("Schema")]),t._v(" trait, make sure to override "),a("code",[t._v("nullable")]),t._v(" and "),a("code",[t._v("canFail")]),t._v(" methods to return the correct values.\nAll types that return "),a("code",[t._v("false")]),t._v(" for "),a("code",[t._v("nullable")]),t._v(" and "),a("code",[t._v("true")]),t._v(" for "),a("code",[t._v("canFail")]),t._v(" will be treated as semantically non-nullable.")]),t._v(" "),a("h2",{attrs:{id:"building-schemas-by-hand"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#building-schemas-by-hand"}},[t._v("#")]),t._v(" Building Schemas by hand")]),t._v(" "),a("p",[t._v("Sometimes for whatever reason schema generation fails. This can happen if your schema has co-recursive types and derivation is unable\nto generate a schema for them. In cases like these you may need to instead create your own schema by hand.")]),t._v(" "),a("p",[t._v("Consider the case where you have three types which create cyclical dependencies on one another")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("UIO\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" users"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("User"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" parent"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" organization"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Organization"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Organization"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" groups"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" User"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" group"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("These three types all depend on one another and if you attempt to generate a schema from them you will either end up with compiler errors or you will end up with a nasty runtime\nerror from a "),a("code",[t._v("NullPointerException")]),t._v(". To help the compiler out we can hand generate the types for these case classes instead.")]),t._v(" "),a("code-group",[a("code-block",{attrs:{title:"Scala 2",active:""}},[a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("obj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" groupSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" obj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Group"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"A group of users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" ft "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("users"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"parent"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parent"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"organization"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("organization"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" orgSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Organization"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" obj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Organization"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"An organization of groups"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" ft "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"groups"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("groups"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" userSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" User"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" obj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"User"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"A user of the service"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" ft "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"group"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3"}},[a("div",{staticClass:"language-scala 3 mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("customObj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" customObj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Group"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"A group of users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("users"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"parent"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parent"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"organization"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("organization"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Organization"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" customObj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Organization"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"An organization of groups"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"groups"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("groups"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" User"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" customObj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"User"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"A user of the service"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"group"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])],1),t._v(" "),a("h2",{attrs:{id:"schema-transformations"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#schema-transformations"}},[t._v("#")]),t._v(" Schema transformations")]),t._v(" "),a("p",[t._v("It is also possible to modify your schemas after they have been generated.\nThis can be useful if you want to rename or remove particular types, fields or arguments from your schema without modifying the related Scala types.")]),t._v(" "),a("p",[t._v("For that, simply use the "),a("code",[t._v("GraphQL#transform")]),t._v(" method and provide one of the possible transformers:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("RenameType")]),t._v(" to rename types (providing a list of "),a("code",[t._v("(OldName -> NewName)")]),t._v(")")]),t._v(" "),a("li",[a("code",[t._v("RenameField")]),t._v(" to rename a field (providing a list of "),a("code",[t._v("(TypeName -> oldName -> newName)")]),t._v(")")]),t._v(" "),a("li",[a("code",[t._v("RenameArgument")]),t._v(" to rename an argument (providing a list of "),a("code",[t._v("(TypeName -> fieldName -> oldArgumentName -> newArgumentName)")]),t._v(")")]),t._v(" "),a("li",[a("code",[t._v("ExcludeField")]),t._v(" to exclude a field (providing a list of "),a("code",[t._v("(TypeName -> fieldToBeExcluded)")]),t._v(")")]),t._v(" "),a("li",[a("code",[t._v("ExcludeInputField")]),t._v(" to exclude an input field (providing a list of "),a("code",[t._v("(TypeName -> fieldToBeExcluded)")]),t._v(")")]),t._v(" "),a("li",[a("code",[t._v("ExcludeArgument")]),t._v(" to exclude an argument (providing a list of "),a("code",[t._v("(TypeName -> fieldName -> argumentToBeExcluded)")]),t._v(")")]),t._v(" "),a("li",[a("code",[t._v("ExcludeDirectives")]),t._v(" to exclude fields and input fields annotated with a specific directive (providing a list of "),a("code",[t._v("GQLDirective")]),t._v(" or a "),a("code",[t._v("Directive => Boolean")]),t._v(" predicate)")])]),t._v(" "),a("p",[t._v("In the following example, we can expose 2 different APIs created from the same schema: the v1 API will not expose the "),a("code",[t._v("nicknames")]),t._v(" field of the "),a("code",[t._v("Character")]),t._v(" type.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Beta"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" GQLDirective"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"beta"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("character"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@Beta")]),t._v(" nicknames"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" apiBeta "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" apiV1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" apiBeta"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("transform"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Transformer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ExcludeDirectives"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Beta"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// alternatively:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// val apiV1 = apiBeta.transform(Transformer.ExcludeField("Character" -> "nicknames"))')]),t._v("\n")])])]),a("p",[t._v("You can also create your own transformers by extending the "),a("code",[t._v("Transformer")]),t._v(" trait and implementing its methods.")])],1)}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/38.8217efc7.js b/docs/assets/js/38.aa2dfc31.js similarity index 99% rename from docs/assets/js/38.8217efc7.js rename to docs/assets/js/38.aa2dfc31.js index 3d8150f0f6..bb677910e9 100644 --- a/docs/assets/js/38.8217efc7.js +++ b/docs/assets/js/38.aa2dfc31.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[38],{320:function(t,a,s){"use strict";s.r(a);var n=s(14),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"code-generation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#code-generation"}},[t._v("#")]),t._v(" Code generation")]),t._v(" "),a("p",[t._v("If you want a workflow where you first edit a GraphQL schema file, and then generate type-safe server stubs, Caliban has your back.")]),t._v(" "),a("p",[t._v("You'll first need to add the following dependency to your "),a("code",[t._v("project/plugins.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("addSbtPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-codegen-sbt"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("You then enable it in your "),a("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" _root_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tools"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Codegen\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" myproject "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" project\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// enable caliban codegen plugin")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("enablePlugins"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CalibanPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("settings"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// add code generation settings")]),t._v("\n Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" caliban "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" calibanSettings "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Seq"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n calibanSetting"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"myproject/src/main/graphql/myapi.graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// important to set this, otherwise you'll get client code")]),t._v("\n _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("genType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Codegen"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("GenType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// you can customize the codegen further with this DSL")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("clientName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"NameOfApi.scala"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("packageName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"myproject.mypackage"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("You can also generate it manually using the following sbt command:")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("calibanGenSchema schemaPath outputPath [options]\n")])])]),a("p",[t._v("Example:")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("calibanGenSchema project/schema.graphql src/main/MyAPI.scala --addDerives true\n")])])]),a("h2",{attrs:{id:"options"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#options"}},[t._v("#")]),t._v(" Options")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("scalafmtPath")]),t._v(": Specifies the configuration file for Scalafmt. Default: "),a("code",[t._v(".scalafmt.conf")]),t._v(".")]),t._v(" "),a("li",[a("code",[t._v("headers")]),t._v(": Provides request headers when "),a("code",[t._v("schemaPath")]),t._v(" is a URL.")]),t._v(" "),a("li",[a("code",[t._v("packageName")]),t._v(": Overrides the package name derived from the folder of "),a("code",[t._v("outputPath")]),t._v(".")]),t._v(" "),a("li",[a("code",[t._v("effect")]),t._v(": Overrides the default effect ("),a("code",[t._v("zio.UIO")]),t._v(") for wrapping fields in Queries and Mutations.")]),t._v(" "),a("li",[a("code",[t._v("scalarMappings")]),t._v(": Forces a mapping between a GraphQL type and a Scala class (e.g., scalars).")]),t._v(" "),a("li",[a("code",[t._v("imports")]),t._v(": Adds additional imports to the generated code.")]),t._v(" "),a("li",[a("code",[t._v("abstractEffectType")]),t._v(": Indicates that the effect type is abstract. Fields in Queries and Mutations will return "),a("code",[t._v("F[_]")]),t._v(".")]),t._v(" "),a("li",[a("code",[t._v("preserveInputNames")]),t._v(": Disables the default behavior of appending "),a("code",[t._v("Input")]),t._v(" to the type name of input types in the derived schema.")]),t._v(" "),a("li",[a("code",[t._v("addDerives")]),t._v(": Adds "),a("code",[t._v("derives")]),t._v(" clauses for type class instance derivation in Scala 3.")]),t._v(" "),a("li",[a("code",[t._v("envForDerives")]),t._v(": Specifies the type alias for your ZIO Environment when using "),a("code",[t._v("derives")]),t._v(" and a ZIO Environment other than "),a("code",[t._v("Any")]),t._v(".")])]),t._v(" "),a("h2",{attrs:{id:"lazy-evaluation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#lazy-evaluation"}},[t._v("#")]),t._v(" Lazy evaluation")]),t._v(" "),a("p",[t._v("The main difference between generating code for client usage and for server usage is that on the server you need to account for\ncode which should only be evaluated if the client requests the field!")]),t._v(" "),a("p",[t._v("You can annotate this directly in the graphql schema by creating a "),a("code",[t._v("@lazy")]),t._v(" directive.")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("directive")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("on")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("FIELD_DEFINITION")]),t._v("\n")])])]),a("p",[t._v("You can then annotate fields in the graphql schema like this:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("directive")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("on")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("FIELD_DEFINITION")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyType")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("myLazyField")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@lazy")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("myField")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("And you'll get a case class which looks something like this:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("myLazyField"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" myField"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("When implementing this, "),a("code",[t._v("myLazyField")]),t._v(" will only be evaluated if the client requested it in the query")]),t._v(" "),a("h2",{attrs:{id:"newtype-declaration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#newtype-declaration"}},[t._v("#")]),t._v(" Newtype declaration")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("@newtype")]),t._v(" directive in caliban allows you to wrap your GraphQL fields into statically\ntyped IDs for backend. For clients, they can use the GraphQL as before and do not\nhave to adjust their typing, or optionally can generate stronger typed IDs using\nthe directive.")]),t._v(" "),a("p",[t._v("In the following example we want to encapsulate "),a("code",[t._v("id : ID")]),t._v(" as FooId for better type safety, so\nwe use the "),a("code",[t._v("@newtype")]),t._v(" directive on the "),a("code",[t._v("Query")]),t._v(" and Foo object type.\nOn mutation, we are passing an optional field of String. To avoid mixing with other String\ntypes in backend code we decided to create a "),a("code",[t._v("@newtype")]),t._v(" of Bar instead.")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("directive")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@newtype")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("on")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("FIELD_DEFINITION")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("ARGUMENT_DEFINITION")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("INPUT_FIELD_DEFINITION")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Query")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property-query"}},[t._v("getFoo")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("id")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("ID")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@newtype")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"FooId"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Foo")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mutation")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("updateFoo")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("foo")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token atom-input class-name"}},[t._v("FooInput")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Foo")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Foo")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("id")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("ID")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@newtype")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"FooId"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("input")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token atom-input class-name"}},[t._v("FooInput")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("maybeBar")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@newtype")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bar"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("With Scalar mapping for ID set to Int, it would give you the following case classes.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("AnyVal")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("AnyVal")]),t._v("\n")])])]),a("p",[t._v("The "),a("code",[t._v("extends AnyVal")]),t._v(" ensures type erasure in such a way that we do not have to consider this abstraction\non client side, and hence graphql query remains the same as before applying the directive.\nBut for this to work we need to supply some implicit for our schema to understand the AnyVal\nconversion and mapping of the return values using "),a("code",[t._v("@GQLDirective")]),t._v(" annotation.")]),t._v(" "),a("p",[t._v("With this in place our generate type code should look something like this:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Types "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" QueryGetFooArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MutationUpdateFooArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("foo"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FooInput"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("AnyVal")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Bar "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" implicitly"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("contramap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" argBuilder"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" implicitly"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("AnyVal")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" FooId "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" implicitly"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("contramap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" argBuilder"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" implicitly"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Foo"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLDirective")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Directive"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"newtype"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"FooId"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FooId\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" FooInput"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLDirective")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Directive"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"newtype"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bar"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n maybeBar"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" scala"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[38],{318:function(t,a,s){"use strict";s.r(a);var n=s(14),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"code-generation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#code-generation"}},[t._v("#")]),t._v(" Code generation")]),t._v(" "),a("p",[t._v("If you want a workflow where you first edit a GraphQL schema file, and then generate type-safe server stubs, Caliban has your back.")]),t._v(" "),a("p",[t._v("You'll first need to add the following dependency to your "),a("code",[t._v("project/plugins.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("addSbtPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-codegen-sbt"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("You then enable it in your "),a("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" _root_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tools"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Codegen\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" myproject "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" project\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// enable caliban codegen plugin")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("enablePlugins"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CalibanPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("settings"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// add code generation settings")]),t._v("\n Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" caliban "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" calibanSettings "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Seq"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n calibanSetting"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"myproject/src/main/graphql/myapi.graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// important to set this, otherwise you'll get client code")]),t._v("\n _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("genType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Codegen"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("GenType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// you can customize the codegen further with this DSL")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("clientName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"NameOfApi.scala"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("packageName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"myproject.mypackage"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("You can also generate it manually using the following sbt command:")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("calibanGenSchema schemaPath outputPath [options]\n")])])]),a("p",[t._v("Example:")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("calibanGenSchema project/schema.graphql src/main/MyAPI.scala --addDerives true\n")])])]),a("h2",{attrs:{id:"options"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#options"}},[t._v("#")]),t._v(" Options")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("scalafmtPath")]),t._v(": Specifies the configuration file for Scalafmt. Default: "),a("code",[t._v(".scalafmt.conf")]),t._v(".")]),t._v(" "),a("li",[a("code",[t._v("headers")]),t._v(": Provides request headers when "),a("code",[t._v("schemaPath")]),t._v(" is a URL.")]),t._v(" "),a("li",[a("code",[t._v("packageName")]),t._v(": Overrides the package name derived from the folder of "),a("code",[t._v("outputPath")]),t._v(".")]),t._v(" "),a("li",[a("code",[t._v("effect")]),t._v(": Overrides the default effect ("),a("code",[t._v("zio.UIO")]),t._v(") for wrapping fields in Queries and Mutations.")]),t._v(" "),a("li",[a("code",[t._v("scalarMappings")]),t._v(": Forces a mapping between a GraphQL type and a Scala class (e.g., scalars).")]),t._v(" "),a("li",[a("code",[t._v("imports")]),t._v(": Adds additional imports to the generated code.")]),t._v(" "),a("li",[a("code",[t._v("abstractEffectType")]),t._v(": Indicates that the effect type is abstract. Fields in Queries and Mutations will return "),a("code",[t._v("F[_]")]),t._v(".")]),t._v(" "),a("li",[a("code",[t._v("preserveInputNames")]),t._v(": Disables the default behavior of appending "),a("code",[t._v("Input")]),t._v(" to the type name of input types in the derived schema.")]),t._v(" "),a("li",[a("code",[t._v("addDerives")]),t._v(": Adds "),a("code",[t._v("derives")]),t._v(" clauses for type class instance derivation in Scala 3.")]),t._v(" "),a("li",[a("code",[t._v("envForDerives")]),t._v(": Specifies the type alias for your ZIO Environment when using "),a("code",[t._v("derives")]),t._v(" and a ZIO Environment other than "),a("code",[t._v("Any")]),t._v(".")])]),t._v(" "),a("h2",{attrs:{id:"lazy-evaluation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#lazy-evaluation"}},[t._v("#")]),t._v(" Lazy evaluation")]),t._v(" "),a("p",[t._v("The main difference between generating code for client usage and for server usage is that on the server you need to account for\ncode which should only be evaluated if the client requests the field!")]),t._v(" "),a("p",[t._v("You can annotate this directly in the graphql schema by creating a "),a("code",[t._v("@lazy")]),t._v(" directive.")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("directive")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("on")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("FIELD_DEFINITION")]),t._v("\n")])])]),a("p",[t._v("You can then annotate fields in the graphql schema like this:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("directive")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("on")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("FIELD_DEFINITION")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyType")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("myLazyField")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@lazy")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("myField")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("And you'll get a case class which looks something like this:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("myLazyField"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" myField"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("When implementing this, "),a("code",[t._v("myLazyField")]),t._v(" will only be evaluated if the client requested it in the query")]),t._v(" "),a("h2",{attrs:{id:"newtype-declaration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#newtype-declaration"}},[t._v("#")]),t._v(" Newtype declaration")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("@newtype")]),t._v(" directive in caliban allows you to wrap your GraphQL fields into statically\ntyped IDs for backend. For clients, they can use the GraphQL as before and do not\nhave to adjust their typing, or optionally can generate stronger typed IDs using\nthe directive.")]),t._v(" "),a("p",[t._v("In the following example we want to encapsulate "),a("code",[t._v("id : ID")]),t._v(" as FooId for better type safety, so\nwe use the "),a("code",[t._v("@newtype")]),t._v(" directive on the "),a("code",[t._v("Query")]),t._v(" and Foo object type.\nOn mutation, we are passing an optional field of String. To avoid mixing with other String\ntypes in backend code we decided to create a "),a("code",[t._v("@newtype")]),t._v(" of Bar instead.")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("directive")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@newtype")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("on")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("FIELD_DEFINITION")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("ARGUMENT_DEFINITION")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("INPUT_FIELD_DEFINITION")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Query")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property-query"}},[t._v("getFoo")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("id")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("ID")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@newtype")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"FooId"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Foo")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mutation")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("updateFoo")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("foo")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token atom-input class-name"}},[t._v("FooInput")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Foo")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Foo")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("id")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("ID")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@newtype")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"FooId"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("input")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token atom-input class-name"}},[t._v("FooInput")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("maybeBar")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@newtype")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bar"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("With Scalar mapping for ID set to Int, it would give you the following case classes.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("AnyVal")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("AnyVal")]),t._v("\n")])])]),a("p",[t._v("The "),a("code",[t._v("extends AnyVal")]),t._v(" ensures type erasure in such a way that we do not have to consider this abstraction\non client side, and hence graphql query remains the same as before applying the directive.\nBut for this to work we need to supply some implicit for our schema to understand the AnyVal\nconversion and mapping of the return values using "),a("code",[t._v("@GQLDirective")]),t._v(" annotation.")]),t._v(" "),a("p",[t._v("With this in place our generate type code should look something like this:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Types "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" QueryGetFooArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MutationUpdateFooArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("foo"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FooInput"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("AnyVal")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Bar "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" implicitly"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("contramap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" argBuilder"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" implicitly"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("AnyVal")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" FooId "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" implicitly"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("contramap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" argBuilder"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" implicitly"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Foo"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLDirective")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Directive"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"newtype"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"FooId"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FooId\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" FooInput"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLDirective")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Directive"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"newtype"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bar"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n maybeBar"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" scala"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/39.0ecd4a9a.js b/docs/assets/js/39.7e53426c.js similarity index 99% rename from docs/assets/js/39.0ecd4a9a.js rename to docs/assets/js/39.7e53426c.js index 4927aaa7eb..6dbf206b0b 100644 --- a/docs/assets/js/39.0ecd4a9a.js +++ b/docs/assets/js/39.7e53426c.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[39],{321:function(t,s,a){"use strict";a.r(s);var n=a(14),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"stitching"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#stitching"}},[t._v("#")]),t._v(" Stitching")]),t._v(" "),s("p",[s("strong",[t._v("Stitching")]),t._v(" is a part of "),s("code",[t._v("caliban-tools")]),t._v(" which can be used to use parts of another GraphQL API from an API you're building in situations where using Apollo federation isn't an option. You can also use it to fully subsume and proxy another GraphQL schema.")]),t._v(" "),s("p",[t._v("In general, Federation should be your preferred choice.")]),t._v(" "),s("p",[t._v("You should also be careful when using stitching since it's very easy to pull in large parts of an external schema's types and structure into your API. This can make it error prone since the likelihood that you'll get type clashes between your API and the API you're stitching in quickly increases.")]),t._v(" "),s("h2",{attrs:{id:"dependencies"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#dependencies"}},[t._v("#")]),t._v(" Dependencies")]),t._v(" "),s("p",[t._v("In order to use stitching, add "),s("code",[t._v("caliban-tools")]),t._v(" to your dependencies:")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-tools"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),t._v("\n")])])]),s("h2",{attrs:{id:"stitching-in-action"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#stitching-in-action"}},[t._v("#")]),t._v(" Stitching in Action")]),t._v(" "),s("p",[t._v("Let's start out by defining our API. We'll have "),s("code",[t._v("AppUser")]),t._v(" profiles, that has a linked "),s("code",[t._v("featuredRepository")]),t._v(". For the "),s("code",[t._v("featuredRepository")]),t._v(", we want to leverage "),s("a",{attrs:{href:"https://docs.github.com/en/graphql",target:"_blank",rel:"noopener noreferrer"}},[t._v("Github's GraphQL API"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("div",{staticClass:"language-scala mdoc:silent extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" StitchingExample "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" GenericSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" AppUser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" name"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" featuredRepository"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" name"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" GetUserQuery"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" repository"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GetUser"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GetUserQuery "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" UIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("AppUser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n RootResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GetUser "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" query "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n Random"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nextUUID"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("uuid "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n AppUser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n id "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" uuid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toString"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n name "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" query"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n featuredRepository "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("query"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" query"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("Now let's integrate with the Github API!")]),t._v(" "),s("p",[t._v("In order to do this we're going to do a couple of things:")]),t._v(" "),s("ol",[s("li",[t._v("Load the introspection schema from Github's API")]),t._v(" "),s("li",[t._v("Parse the introspected schema into a "),s("code",[t._v("caliban.introspection.adt.__Schema")])]),t._v(" "),s("li",[t._v("Use the parsed schema to generate an "),s("code",[t._v("implicit Schema[R, A]")]),t._v(" for the entities we're stitching. This effectively replaces our own schema with one from Github.")]),t._v(" "),s("li",[t._v("Teach our implicit schema how to map our local resolver to a query that can be resolved remotely by calling Github's API.")])]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" GITHUB_API "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https://api.github.com/graphql"')]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n sttpClient "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ZIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("environment"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("SttpClient"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 1")]),t._v("\n schemaLoader "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" SchemaLoader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromIntrospection"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GITHUB_API"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n schema "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" schemaLoader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("load\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 2")]),t._v("\n remoteSchema "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ZIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromOption"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RemoteSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parseRemoteSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n remoteSchemaResolvers "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" RemoteSchemaResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("remoteSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 3")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" githubProfileSchema"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n remoteSchemaResolvers\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("remoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Repository"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 4")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Here we need to translate our local `Repository` case class into")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// a top-level query which can be issued towards Github's API.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We do this by accepting a `caliban.execution.Field`, representing")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// all the selected fields for a repository and map that to the")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// top-level `repository` query in the Github API.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This means the final query will end up looking something like this:")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// query {")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// repository(owner: r.args.owner, name: r.args.name) {")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// . ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// }")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// }")]),t._v("\n RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromFunction"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ResolveRequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n name "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"repository"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n arguments "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Map"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"owner"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" Value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" Value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromUrl"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GITHUB_API"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("provide"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sttpClient"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("However, when running this we will experience failing requests due to "),s("code",[t._v("401 Unauthorized")]),t._v(". This is because all queries to Github's API requires authorization to be provided. In order to fix this, we need to add authorization to both the introspection query as well as our remote resolver. We also need a config module that can provide us with a Github token based on the value of "),s("code",[t._v("GITHUB_TOKEN")]),t._v(" in our environment.")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Configuration"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("githubToken"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Configuration "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" fromEnvironment "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n githubToken "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" read"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GITHUB_TOKEN"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" Configuration"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("githubToken"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toLayer\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" read"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Task"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Task"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("effect"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n sys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("env"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("We can now update the introspection query to use our token:")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n config "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ZIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("environment"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Has"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Configuration"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n schemaLoader "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" SchemaLoader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromIntrospection"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GITHUB_API"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Options"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Authorization"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string-interpolation"}},[s("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bearer ')]),s("span",{pre:!0,attrs:{class:"token interpolation"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),s("span",{pre:!0,attrs:{class:"token expression"}},[t._v("config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("get"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("githubToken")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")])]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n")])])]),s("p",[t._v("as well as update our resolver to authorize our request.")]),t._v(" "),s("p",[t._v("In order to do this, we can use "),s("code",[t._v("RemoteResolver[R, E, A, B]")]),t._v(" which lets us compose resolution steps via "),s("code",[t._v(">>>")]),t._v(".")]),t._v(" "),s("p",[t._v("In order to make this code easier, we can extract the mechanics around sending the actual request:")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" apiRequest "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toQuery "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GITHUB_API"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromFunctionM"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" HttpRequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n config "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ZIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("service"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Configuration"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Authorization"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-interpolation"}},[s("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bearer ')]),s("span",{pre:!0,attrs:{class:"token interpolation"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),s("span",{pre:!0,attrs:{class:"token expression"}},[t._v("config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("githubToken")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")])]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("execute "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("unwrap\n")])])]),s("p",[t._v("And now we can use our new "),s("code",[t._v("apiRequest")]),t._v(" when resolving our "),s("code",[t._v("Schema[ZEnv, Repository]")]),t._v(":")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" githubProfileSchema"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n remoteSchemaResolvers\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("remoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Repository"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromFunction"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ResolveRequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n name "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"repository"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n arguments "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Map"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"owner"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" Value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" Value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" apiRequest\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("provide"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sttpClient "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("All that's left to do is to hook up to an HTTP server and configure a Github API token. And now you have an API that can handle queries such as these:")]),t._v(" "),s("div",{staticClass:"language-graphql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-graphql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("query")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property-query"}},[t._v("GetUser")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ghostdogpr"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("repository")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("id")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("name")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("featuredRepository")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property-query"}},[t._v("pullRequests")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("states")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("OPEN")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("first")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("edges")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("node")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("title")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("author")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("login")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("See the "),s("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/stitching",target:"_blank",rel:"noopener noreferrer"}},[t._v("examples directory"),s("OutboundLink")],1),t._v(" for a full example.")]),t._v(" "),s("h2",{attrs:{id:"things-not-yet-supported"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#things-not-yet-supported"}},[t._v("#")]),t._v(" Things not yet supported")]),t._v(" "),s("ul",[s("li",[t._v("Type renaming.")]),t._v(" "),s("li",[t._v("Type conflict resolution strategies.")])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[39],{320:function(t,s,a){"use strict";a.r(s);var n=a(14),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"stitching"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#stitching"}},[t._v("#")]),t._v(" Stitching")]),t._v(" "),s("p",[s("strong",[t._v("Stitching")]),t._v(" is a part of "),s("code",[t._v("caliban-tools")]),t._v(" which can be used to use parts of another GraphQL API from an API you're building in situations where using Apollo federation isn't an option. You can also use it to fully subsume and proxy another GraphQL schema.")]),t._v(" "),s("p",[t._v("In general, Federation should be your preferred choice.")]),t._v(" "),s("p",[t._v("You should also be careful when using stitching since it's very easy to pull in large parts of an external schema's types and structure into your API. This can make it error prone since the likelihood that you'll get type clashes between your API and the API you're stitching in quickly increases.")]),t._v(" "),s("h2",{attrs:{id:"dependencies"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#dependencies"}},[t._v("#")]),t._v(" Dependencies")]),t._v(" "),s("p",[t._v("In order to use stitching, add "),s("code",[t._v("caliban-tools")]),t._v(" to your dependencies:")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-tools"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),t._v("\n")])])]),s("h2",{attrs:{id:"stitching-in-action"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#stitching-in-action"}},[t._v("#")]),t._v(" Stitching in Action")]),t._v(" "),s("p",[t._v("Let's start out by defining our API. We'll have "),s("code",[t._v("AppUser")]),t._v(" profiles, that has a linked "),s("code",[t._v("featuredRepository")]),t._v(". For the "),s("code",[t._v("featuredRepository")]),t._v(", we want to leverage "),s("a",{attrs:{href:"https://docs.github.com/en/graphql",target:"_blank",rel:"noopener noreferrer"}},[t._v("Github's GraphQL API"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("div",{staticClass:"language-scala mdoc:silent extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" StitchingExample "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" GenericSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" AppUser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" name"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" featuredRepository"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" name"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" GetUserQuery"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" repository"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GetUser"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GetUserQuery "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" UIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("AppUser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n RootResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GetUser "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" query "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n Random"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nextUUID"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("uuid "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n AppUser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n id "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" uuid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toString"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n name "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" query"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n featuredRepository "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("query"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" query"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("Now let's integrate with the Github API!")]),t._v(" "),s("p",[t._v("In order to do this we're going to do a couple of things:")]),t._v(" "),s("ol",[s("li",[t._v("Load the introspection schema from Github's API")]),t._v(" "),s("li",[t._v("Parse the introspected schema into a "),s("code",[t._v("caliban.introspection.adt.__Schema")])]),t._v(" "),s("li",[t._v("Use the parsed schema to generate an "),s("code",[t._v("implicit Schema[R, A]")]),t._v(" for the entities we're stitching. This effectively replaces our own schema with one from Github.")]),t._v(" "),s("li",[t._v("Teach our implicit schema how to map our local resolver to a query that can be resolved remotely by calling Github's API.")])]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" GITHUB_API "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https://api.github.com/graphql"')]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n sttpClient "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ZIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("environment"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("SttpClient"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 1")]),t._v("\n schemaLoader "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" SchemaLoader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromIntrospection"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GITHUB_API"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n schema "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" schemaLoader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("load\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 2")]),t._v("\n remoteSchema "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ZIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromOption"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RemoteSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parseRemoteSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n remoteSchemaResolvers "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" RemoteSchemaResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("remoteSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 3")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" githubProfileSchema"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n remoteSchemaResolvers\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("remoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Repository"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 4")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Here we need to translate our local `Repository` case class into")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// a top-level query which can be issued towards Github's API.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We do this by accepting a `caliban.execution.Field`, representing")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// all the selected fields for a repository and map that to the")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// top-level `repository` query in the Github API.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This means the final query will end up looking something like this:")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// query {")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// repository(owner: r.args.owner, name: r.args.name) {")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// . ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// }")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// }")]),t._v("\n RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromFunction"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ResolveRequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n name "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"repository"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n arguments "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Map"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"owner"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" Value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" Value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromUrl"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GITHUB_API"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("provide"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sttpClient"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("However, when running this we will experience failing requests due to "),s("code",[t._v("401 Unauthorized")]),t._v(". This is because all queries to Github's API requires authorization to be provided. In order to fix this, we need to add authorization to both the introspection query as well as our remote resolver. We also need a config module that can provide us with a Github token based on the value of "),s("code",[t._v("GITHUB_TOKEN")]),t._v(" in our environment.")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Configuration"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("githubToken"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Configuration "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" fromEnvironment "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n githubToken "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" read"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GITHUB_TOKEN"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" Configuration"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("githubToken"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toLayer\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" read"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Task"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Task"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("effect"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n sys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("env"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("We can now update the introspection query to use our token:")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n config "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ZIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("environment"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Has"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Configuration"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n schemaLoader "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" SchemaLoader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromIntrospection"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GITHUB_API"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Options"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Authorization"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string-interpolation"}},[s("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bearer ')]),s("span",{pre:!0,attrs:{class:"token interpolation"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),s("span",{pre:!0,attrs:{class:"token expression"}},[t._v("config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("get"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("githubToken")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")])]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n")])])]),s("p",[t._v("as well as update our resolver to authorize our request.")]),t._v(" "),s("p",[t._v("In order to do this, we can use "),s("code",[t._v("RemoteResolver[R, E, A, B]")]),t._v(" which lets us compose resolution steps via "),s("code",[t._v(">>>")]),t._v(".")]),t._v(" "),s("p",[t._v("In order to make this code easier, we can extract the mechanics around sending the actual request:")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" apiRequest "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toQuery "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GITHUB_API"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromFunctionM"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" HttpRequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n config "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ZIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("service"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Configuration"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Authorization"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-interpolation"}},[s("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bearer ')]),s("span",{pre:!0,attrs:{class:"token interpolation"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),s("span",{pre:!0,attrs:{class:"token expression"}},[t._v("config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("githubToken")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")])]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("execute "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("unwrap\n")])])]),s("p",[t._v("And now we can use our new "),s("code",[t._v("apiRequest")]),t._v(" when resolving our "),s("code",[t._v("Schema[ZEnv, Repository]")]),t._v(":")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" githubProfileSchema"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n remoteSchemaResolvers\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("remoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Repository"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromFunction"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ResolveRequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n name "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"repository"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n arguments "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Map"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"owner"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" Value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" Value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" apiRequest\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("provide"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sttpClient "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("All that's left to do is to hook up to an HTTP server and configure a Github API token. And now you have an API that can handle queries such as these:")]),t._v(" "),s("div",{staticClass:"language-graphql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-graphql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("query")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property-query"}},[t._v("GetUser")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ghostdogpr"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("repository")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("id")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("name")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("featuredRepository")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property-query"}},[t._v("pullRequests")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("states")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("OPEN")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("first")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("edges")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("node")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("title")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("author")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("login")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("See the "),s("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/stitching",target:"_blank",rel:"noopener noreferrer"}},[t._v("examples directory"),s("OutboundLink")],1),t._v(" for a full example.")]),t._v(" "),s("h2",{attrs:{id:"things-not-yet-supported"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#things-not-yet-supported"}},[t._v("#")]),t._v(" Things not yet supported")]),t._v(" "),s("ul",[s("li",[t._v("Type renaming.")]),t._v(" "),s("li",[t._v("Type conflict resolution strategies.")])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/40.72c059af.js b/docs/assets/js/40.5a62ccfc.js similarity index 96% rename from docs/assets/js/40.72c059af.js rename to docs/assets/js/40.5a62ccfc.js index f22edf2c3d..bb1829cad9 100644 --- a/docs/assets/js/40.72c059af.js +++ b/docs/assets/js/40.5a62ccfc.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[40],{322:function(t,e,a){"use strict";a.r(e);var s=a(14),o=Object(s.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"getting-started"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#getting-started"}},[t._v("#")]),t._v(" Getting Started")]),t._v(" "),e("p",[t._v("Caliban comes with a module called "),e("code",[t._v("caliban-tools")]),t._v(" that exposes some useful features:")]),t._v(" "),e("ul",[e("li",[t._v("all the code generation features from "),e("code",[t._v("caliban-codegen-sbt")]),t._v(", so that you can use them without sbt: see "),e("code",[t._v("caliban.tools.Codegen")]),t._v(".")]),t._v(" "),e("li",[t._v("a client for GraphQL introspection: see "),e("code",[t._v("caliban.tools.IntrospectionClient")]),t._v(".")]),t._v(" "),e("li",[t._v("utilities for "),e("RouterLink",{attrs:{to:"/docs/stitching.html"}},[t._v("stitching GraphQL schemas")]),t._v(".")],1),t._v(" "),e("li",[t._v("a way to "),e("RouterLink",{attrs:{to:"/docs/schema-comparison.html"}},[t._v("compare GraphQL schemas")]),t._v(", whether they come from Caliban or a remote server.")],1)]),t._v(" "),e("h2",{attrs:{id:"dependency"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#dependency"}},[t._v("#")]),t._v(" Dependency")]),t._v(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-tools"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.8.1"')]),t._v("\n")])])])])}),[],!1,null,null,null);e.default=o.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[40],{322:function(t,e,a){"use strict";a.r(e);var s=a(14),o=Object(s.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"getting-started"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#getting-started"}},[t._v("#")]),t._v(" Getting Started")]),t._v(" "),e("p",[t._v("Caliban comes with a module called "),e("code",[t._v("caliban-tools")]),t._v(" that exposes some useful features:")]),t._v(" "),e("ul",[e("li",[t._v("all the code generation features from "),e("code",[t._v("caliban-codegen-sbt")]),t._v(", so that you can use them without sbt: see "),e("code",[t._v("caliban.tools.Codegen")]),t._v(".")]),t._v(" "),e("li",[t._v("a client for GraphQL introspection: see "),e("code",[t._v("caliban.tools.IntrospectionClient")]),t._v(".")]),t._v(" "),e("li",[t._v("utilities for "),e("RouterLink",{attrs:{to:"/docs/stitching.html"}},[t._v("stitching GraphQL schemas")]),t._v(".")],1),t._v(" "),e("li",[t._v("a way to "),e("RouterLink",{attrs:{to:"/docs/schema-comparison.html"}},[t._v("compare GraphQL schemas")]),t._v(", whether they come from Caliban or a remote server.")],1)]),t._v(" "),e("h2",{attrs:{id:"dependency"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#dependency"}},[t._v("#")]),t._v(" Dependency")]),t._v(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-tools"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.9.0"')]),t._v("\n")])])])])}),[],!1,null,null,null);e.default=o.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/app.7daa26fd.js b/docs/assets/js/app.cd7b3176.js similarity index 97% rename from docs/assets/js/app.7daa26fd.js rename to docs/assets/js/app.cd7b3176.js index 9dafcc1754..f5fa68a8fd 100644 --- a/docs/assets/js/app.7daa26fd.js +++ b/docs/assets/js/app.cd7b3176.js @@ -1,4 +1,4 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[0],[]]);!function(t){function e(e){for(var r,a,s=e[0],c=e[1],u=e[2],f=0,p=[];f
'};function o(t,e,n){return tn?n:t}function i(t){return 100*(-1+t)}n.configure=function(t){var e,n;for(e in t)void 0!==(n=t[e])&&t.hasOwnProperty(e)&&(r[e]=n);return this},n.status=null,n.set=function(t){var e=n.isStarted();t=o(t,r.minimum,1),n.status=1===t?null:t;var c=n.render(!e),u=c.querySelector(r.barSelector),l=r.speed,f=r.easing;return c.offsetWidth,a((function(e){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),s(u,function(t,e,n){var o;return(o="translate3d"===r.positionUsing?{transform:"translate3d("+i(t)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+i(t)+"%,0)"}:{"margin-left":i(t)+"%"}).transition="all "+e+"ms "+n,o}(t,l,f)),1===t?(s(c,{transition:"none",opacity:1}),c.offsetWidth,setTimeout((function(){s(c,{transition:"all "+l+"ms linear",opacity:0}),setTimeout((function(){n.remove(),e()}),l)}),l)):setTimeout(e,l)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var t=function(){setTimeout((function(){n.status&&(n.trickle(),t())}),r.trickleSpeed)};return r.trickle&&t(),this},n.done=function(t){return t||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(t){var e=n.status;return e?("number"!=typeof t&&(t=(1-e)*o(Math.random()*e,.1,.95)),e=o(e+t,0,.994),n.set(e)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},t=0,e=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===e&&n.start(),t++,e++,r.always((function(){0==--e?(t=0,n.done()):n.set((t-e)/t)})),this):this},n.render=function(t){if(n.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var e=document.createElement("div");e.id="nprogress",e.innerHTML=r.template;var o,a=e.querySelector(r.barSelector),c=t?"-100":i(n.status||0),l=document.querySelector(r.parent);return s(a,{transition:"all 0 linear",transform:"translate3d("+c+"%,0,0)"}),r.showSpinner||(o=e.querySelector(r.spinnerSelector))&&p(o),l!=document.body&&u(l,"nprogress-custom-parent"),l.appendChild(e),e},n.remove=function(){l(document.documentElement,"nprogress-busy"),l(document.querySelector(r.parent),"nprogress-custom-parent");var t=document.getElementById("nprogress");t&&p(t)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var t=document.body.style,e="WebkitTransform"in t?"Webkit":"MozTransform"in t?"Moz":"msTransform"in t?"ms":"OTransform"in t?"O":"";return e+"Perspective"in t?"translate3d":e+"Transform"in t?"translate":"margin"};var a=function(){var t=[];function e(){var n=t.shift();n&&n(e)}return function(n){t.push(n),1==t.length&&e()}}(),s=function(){var t=["Webkit","O","Moz","ms"],e={};function n(n){return n=n.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(t,e){return e.toUpperCase()})),e[n]||(e[n]=function(e){var n=document.body.style;if(e in n)return e;for(var r,o=t.length,i=e.charAt(0).toUpperCase()+e.slice(1);o--;)if((r=t[o]+i)in n)return r;return e}(n))}function r(t,e,r){e=n(e),t.style[e]=r}return function(t,e){var n,o,i=arguments;if(2==i.length)for(n in e)void 0!==(o=e[n])&&e.hasOwnProperty(n)&&r(t,n,o);else r(t,i[1],i[2])}}();function c(t,e){return("string"==typeof t?t:f(t)).indexOf(" "+e+" ")>=0}function u(t,e){var n=f(t),r=n+e;c(n,e)||(t.className=r.substring(1))}function l(t,e){var n,r=f(t);c(t,e)&&(n=r.replace(" "+e+" "," "),t.className=n.substring(1,n.length-1))}function f(t){return(" "+(t.className||"")+" ").replace(/\s+/gi," ")}function p(t){t&&t.parentNode&&t.parentNode.removeChild(t)}return n})?r.call(e,n,e,t):r)||(t.exports=o)},function(t,e,n){"use strict";var r=n(0),o=n(45).f,i=n(12),a=n(92),s=n(33),c=n(61),u=n(119);t.exports=function(t,e){var n,l,f,p,d,h=t.target,v=t.global,m=t.stat;if(n=v?r:m?r[h]||s(h,{}):r[h]&&r[h].prototype)for(l in e){if(p=e[l],f=t.dontCallGetSet?(d=o(n,l))&&d.value:n[l],!u(v?l:h+(m?".":"#")+l,t.forced)&&void 0!==f){if(typeof p==typeof f)continue;c(p,f)}(t.sham||f&&f.sham)&&i(p,"sham",!0),a(n,l,p,t)}}},function(t,e,n){"use strict";var r=n(25),o=Function.prototype.call;t.exports=r?o.bind(o):function(){return o.apply(o,arguments)}},function(t,e,n){"use strict";var r=n(3);t.exports=!r((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")}))},function(t,e,n){"use strict";t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},function(t,e,n){"use strict";var r=n(46),o=n(28);t.exports=function(t){return r(o(t))}},function(t,e,n){"use strict";var r=n(47),o=TypeError;t.exports=function(t){if(r(t))throw new o("Can't call method on "+t);return t}},function(t,e,n){"use strict";var r=n(0),o=n(1),i=function(t){return o(t)?t:void 0};t.exports=function(t,e){return arguments.length<2?i(r[t]):r[t]&&r[t][e]}},function(t,e,n){"use strict";var r=n(1),o=n(101),i=TypeError;t.exports=function(t){if(r(t))return t;throw new i(o(t)+" is not a function")}},function(t,e,n){"use strict";var r=n(0),o=n(55),i=n(8),a=n(57),s=n(52),c=n(51),u=r.Symbol,l=o("wks"),f=c?u.for||u:u&&u.withoutSetter||a;t.exports=function(t){return i(l,t)||(l[t]=s&&i(u,t)?u[t]:f("Symbol."+t)),l[t]}},function(t,e,n){"use strict";var r=n(56),o=n(0),i=n(33),a=t.exports=o["__core-js_shared__"]||i("__core-js_shared__",{});(a.versions||(a.versions=[])).push({version:"3.38.1",mode:r?"pure":"global",copyright:"© 2014-2024 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.38.1/LICENSE",source:"https://github.com/zloirock/core-js"})},function(t,e,n){"use strict";var r=n(0),o=Object.defineProperty;t.exports=function(t,e){try{o(r,t,{value:e,configurable:!0,writable:!0})}catch(n){r[t]=e}return e}},function(t,e,n){"use strict";var r=n(28),o=Object;t.exports=function(t){return o(r(t))}},function(t,e,n){"use strict";var r=n(116);t.exports=function(t){return r(t.length)}},function(t,e,n){var r=n(144),o=n(10),i=Object.prototype,a=i.hasOwnProperty,s=i.propertyIsEnumerable,c=r(function(){return arguments}())?r:function(t){return o(t)&&a.call(t,"callee")&&!s.call(t,"callee")};t.exports=c},function(t,e,n){var r=n(9)(n(7),"Map");t.exports=r},function(t,e){t.exports=function(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}},function(t,e,n){var r=n(164),o=n(171),i=n(173),a=n(174),s=n(175);function c(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e-1&&t%1==0&&t<=9007199254740991}},function(t,e,n){var r=n(4),o=n(43),i=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,a=/^\w*$/;t.exports=function(t,e){if(r(t))return!1;var n=typeof t;return!("number"!=n&&"symbol"!=n&&"boolean"!=n&&null!=t&&!o(t))||(a.test(t)||!i.test(t)||null!=e&&t in Object(e))}},function(t,e,n){var r=n(11),o=n(10);t.exports=function(t){return"symbol"==typeof t||o(t)&&"[object Symbol]"==r(t)}},function(t,e){t.exports=function(t){return t}},function(t,e,n){"use strict";var r=n(5),o=n(24),i=n(98),a=n(26),s=n(27),c=n(48),u=n(8),l=n(58),f=Object.getOwnPropertyDescriptor;e.f=r?f:function(t,e){if(t=s(t),e=c(e),l)try{return f(t,e)}catch(t){}if(u(t,e))return a(!o(i.f,t,e),t[e])}},function(t,e,n){"use strict";var r=n(2),o=n(3),i=n(16),a=Object,s=r("".split);t.exports=o((function(){return!a("z").propertyIsEnumerable(0)}))?function(t){return"String"===i(t)?s(t,""):a(t)}:a},function(t,e,n){"use strict";t.exports=function(t){return null==t}},function(t,e,n){"use strict";var r=n(99),o=n(49);t.exports=function(t){var e=r(t,"string");return o(e)?e:e+""}},function(t,e,n){"use strict";var r=n(29),o=n(1),i=n(50),a=n(51),s=Object;t.exports=a?function(t){return"symbol"==typeof t}:function(t){var e=r("Symbol");return o(e)&&i(e.prototype,s(t))}},function(t,e,n){"use strict";var r=n(2);t.exports=r({}.isPrototypeOf)},function(t,e,n){"use strict";var r=n(52);t.exports=r&&!Symbol.sham&&"symbol"==typeof Symbol.iterator},function(t,e,n){"use strict";var r=n(53),o=n(3),i=n(0).String;t.exports=!!Object.getOwnPropertySymbols&&!o((function(){var t=Symbol("symbol detection");return!i(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&r&&r<41}))},function(t,e,n){"use strict";var r,o,i=n(0),a=n(54),s=i.process,c=i.Deno,u=s&&s.versions||c&&c.version,l=u&&u.v8;l&&(o=(r=l.split("."))[0]>0&&r[0]<4?1:+(r[0]+r[1])),!o&&a&&(!(r=a.match(/Edge\/(\d+)/))||r[1]>=74)&&(r=a.match(/Chrome\/(\d+)/))&&(o=+r[1]),t.exports=o},function(t,e,n){"use strict";var r=n(0).navigator,o=r&&r.userAgent;t.exports=o?String(o):""},function(t,e,n){"use strict";var r=n(32);t.exports=function(t,e){return r[t]||(r[t]=e||{})}},function(t,e,n){"use strict";t.exports=!1},function(t,e,n){"use strict";var r=n(2),o=0,i=Math.random(),a=r(1..toString);t.exports=function(t){return"Symbol("+(void 0===t?"":t)+")_"+a(++o+i,36)}},function(t,e,n){"use strict";var r=n(5),o=n(3),i=n(103);t.exports=!r&&!o((function(){return 7!==Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a}))},function(t,e,n){"use strict";var r=n(6),o=String,i=TypeError;t.exports=function(t){if(r(t))return t;throw new i(o(t)+" is not an object")}},function(t,e,n){"use strict";t.exports={}},function(t,e,n){"use strict";var r=n(8),o=n(110),i=n(45),a=n(15);t.exports=function(t,e,n){for(var s=o(e),c=a.f,u=i.f,l=0;ll))return!1;var p=c.get(t),d=c.get(e);if(p&&d)return p==e&&d==t;var h=-1,v=!0,m=2&n?new r:void 0;for(c.set(t,e),c.set(e,t);++h-1&&t%1==0&&t=0&&Math.floor(e)===e&&isFinite(t)}function v(t){return a(t)&&"function"==typeof t.then&&"function"==typeof t.catch}function m(t){return null==t?"":Array.isArray(t)||p(t)&&t.toString===f?JSON.stringify(t,y,2):String(t)}function y(t,e){return e&&e.__v_isRef?e.value:e}function g(t){var e=parseFloat(t);return isNaN(e)?t:e}function b(t,e){for(var n=Object.create(null),r=t.split(","),o=0;o-1)return t.splice(r,1)}}var w=Object.prototype.hasOwnProperty;function O(t,e){return w.call(t,e)}function C(t){var e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}var $=/-(\w)/g,k=C((function(t){return t.replace($,(function(t,e){return e?e.toUpperCase():""}))})),S=C((function(t){return t.charAt(0).toUpperCase()+t.slice(1)})),j=/\B([A-Z])/g,E=C((function(t){return t.replace(j,"-$1").toLowerCase()}));var P=Function.prototype.bind?function(t,e){return t.bind(e)}:function(t,e){function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}return n._length=t.length,n};function A(t,e){e=e||0;for(var n=t.length-e,r=new Array(n);n--;)r[n]=t[n+e];return r}function T(t,e){for(var n in e)t[n]=e[n];return t}function L(t){for(var e={},n=0;n0,Y=J&&J.indexOf("edge/")>0;J&&J.indexOf("android");var tt=J&&/iphone|ipad|ipod|ios/.test(J);J&&/chrome\/\d+/.test(J),J&&/phantomjs/.test(J);var et,nt=J&&J.match(/firefox\/(\d+)/),rt={}.watch,ot=!1;if(Q)try{var it={};Object.defineProperty(it,"passive",{get:function(){ot=!0}}),window.addEventListener("test-passive",null,it)}catch(t){}var at=function(){return void 0===et&&(et=!Q&&"undefined"!=typeof global&&(global.process&&"server"===global.process.env.VUE_ENV)),et},st=Q&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function ct(t){return"function"==typeof t&&/native code/.test(t.toString())}var ut,lt="undefined"!=typeof Symbol&&ct(Symbol)&&"undefined"!=typeof Reflect&&ct(Reflect.ownKeys);ut="undefined"!=typeof Set&&ct(Set)?Set:function(){function t(){this.set=Object.create(null)}return t.prototype.has=function(t){return!0===this.set[t]},t.prototype.add=function(t){this.set[t]=!0},t.prototype.clear=function(){this.set=Object.create(null)},t}();var ft=null;function pt(t){void 0===t&&(t=null),t||ft&&ft._scope.off(),ft=t,t&&t._scope.on()}var dt=function(){function t(t,e,n,r,o,i,a,s){this.tag=t,this.data=e,this.children=n,this.text=r,this.elm=o,this.ns=void 0,this.context=i,this.fnContext=void 0,this.fnOptions=void 0,this.fnScopeId=void 0,this.key=e&&e.key,this.componentOptions=a,this.componentInstance=void 0,this.parent=void 0,this.raw=!1,this.isStatic=!1,this.isRootInsert=!0,this.isComment=!1,this.isCloned=!1,this.isOnce=!1,this.asyncFactory=s,this.asyncMeta=void 0,this.isAsyncPlaceholder=!1}return Object.defineProperty(t.prototype,"child",{get:function(){return this.componentInstance},enumerable:!1,configurable:!0}),t}(),ht=function(t){void 0===t&&(t="");var e=new dt;return e.text=t,e.isComment=!0,e};function vt(t){return new dt(void 0,void 0,void 0,String(t))}function mt(t){var e=new dt(t.tag,t.data,t.children&&t.children.slice(),t.text,t.elm,t.context,t.componentOptions,t.asyncFactory);return e.ns=t.ns,e.isStatic=t.isStatic,e.key=t.key,e.isComment=t.isComment,e.fnContext=t.fnContext,e.fnOptions=t.fnOptions,e.fnScopeId=t.fnScopeId,e.asyncMeta=t.asyncMeta,e.isCloned=!0,e}"function"==typeof SuppressedError&&SuppressedError;var yt=0,gt=[],bt=function(){function t(){this._pending=!1,this.id=yt++,this.subs=[]}return t.prototype.addSub=function(t){this.subs.push(t)},t.prototype.removeSub=function(t){this.subs[this.subs.indexOf(t)]=null,this._pending||(this._pending=!0,gt.push(this))},t.prototype.depend=function(e){t.target&&t.target.addDep(this)},t.prototype.notify=function(t){var e=this.subs.filter((function(t){return t}));for(var n=0,r=e.length;n0&&(Jt((u=t(u,"".concat(n||"","_").concat(r)))[0])&&Jt(f)&&(p[l]=vt(f.text+u[0].text),u.shift()),p.push.apply(p,u)):c(u)?Jt(f)?p[l]=vt(f.text+u):""!==u&&p.push(vt(u)):Jt(u)&&Jt(f)?p[l]=vt(f.text+u.text):(s(e._isVList)&&a(u.tag)&&i(u.key)&&a(n)&&(u.key="__vlist".concat(n,"_").concat(r,"__")),p.push(u)));return p}(t):void 0}function Jt(t){return a(t)&&a(t.text)&&!1===t.isComment}function Zt(t,e){var n,r,i,s,c=null;if(o(t)||"string"==typeof t)for(c=new Array(t.length),n=0,r=t.length;n0,s=e?!!e.$stable:!a,c=e&&e.$key;if(e){if(e._normalized)return e._normalized;if(s&&o&&o!==r&&c===o.$key&&!a&&!o.$hasNormal)return o;for(var u in i={},e)e[u]&&"$"!==u[0]&&(i[u]=me(t,n,u,e[u]))}else i={};for(var l in n)l in i||(i[l]=ye(n,l));return e&&Object.isExtensible(e)&&(e._normalized=i),W(i,"$stable",s),W(i,"$key",c),W(i,"$hasNormal",a),i}function me(t,e,n,r){var i=function(){var e=ft;pt(t);var n=arguments.length?r.apply(null,arguments):r({}),i=(n=n&&"object"==typeof n&&!o(n)?[n]:Qt(n))&&n[0];return pt(e),n&&(!i||1===n.length&&i.isComment&&!he(i))?void 0:n};return r.proxy&&Object.defineProperty(e,n,{get:i,enumerable:!0,configurable:!0}),i}function ye(t,e){return function(){return t[e]}}function ge(t){return{get attrs(){if(!t._attrsProxy){var e=t._attrsProxy={};W(e,"_v_attr_proxy",!0),be(e,t.$attrs,r,t,"$attrs")}return t._attrsProxy},get listeners(){t._listenersProxy||be(t._listenersProxy={},t.$listeners,r,t,"$listeners");return t._listenersProxy},get slots(){return function(t){t._slotsProxy||xe(t._slotsProxy={},t.$scopedSlots);return t._slotsProxy}(t)},emit:P(t.$emit,t),expose:function(e){e&&Object.keys(e).forEach((function(n){return Ut(t,e,n)}))}}}function be(t,e,n,r,o){var i=!1;for(var a in e)a in t?e[a]!==n[a]&&(i=!0):(i=!0,_e(t,a,r,o));for(var a in t)a in e||(i=!0,delete t[a]);return i}function _e(t,e,n,r){Object.defineProperty(t,e,{enumerable:!0,configurable:!0,get:function(){return n[r][e]}})}function xe(t,e){for(var n in e)t[n]=e[n];for(var n in t)n in e||delete t[n]}var we=null;function Oe(t,e){return(t.__esModule||lt&&"Module"===t[Symbol.toStringTag])&&(t=t.default),l(t)?e.extend(t):t}function Ce(t){if(o(t))for(var e=0;edocument.createEvent("Event").timeStamp&&(un=function(){return ln.now()})}var fn=function(t,e){if(t.post){if(!e.post)return 1}else if(e.post)return-1;return t.id-e.id};function pn(){var t,e;for(cn=un(),an=!0,en.sort(fn),sn=0;snsn&&en[n].id>t.id;)n--;en.splice(n+1,0,t)}else en.push(t);on||(on=!0,Fe(pn))}}function hn(t,e){if(t){for(var n=Object.create(null),r=lt?Reflect.ownKeys(t):Object.keys(t),o=0;o-1)if(i&&!O(o,"default"))a=!1;else if(""===a||a===E(t)){var c=Mn(String,o.type);(c<0||s-1:"string"==typeof t?t.split(",").indexOf(e)>-1:!!d(t)&&t.test(e)}function Zn(t,e){var n=t.cache,r=t.keys,o=t._vnode,i=t.$vnode;for(var a in n){var s=n[a];if(s){var c=s.name;c&&!e(c)&&Xn(n,a,r,o)}}i.componentOptions.children=void 0}function Xn(t,e,n,r){var o=t[e];!o||r&&o.tag===r.tag||o.componentInstance.$destroy(),t[e]=null,x(n,e)}Gn.prototype._init=function(t){var e=this;e._uid=Hn++,e._isVue=!0,e.__v_skip=!0,e._scope=new Bt(!0),e._scope.parent=void 0,e._scope._vm=!0,t&&t._isComponent?function(t,e){var n=t.$options=Object.create(t.constructor.options),r=e._parentVnode;n.parent=e.parent,n._parentVnode=r;var o=r.componentOptions;n.propsData=o.propsData,n._parentListeners=o.listeners,n._renderChildren=o.children,n._componentTag=o.tag,e.render&&(n.render=e.render,n.staticRenderFns=e.staticRenderFns)}(e,t):e.$options=Pn(Wn(e.constructor),t||{},e),e._renderProxy=e,e._self=e,function(t){var e=t.$options,n=e.parent;if(n&&!e.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(t)}t.$parent=n,t.$root=n?n.$root:t,t.$children=[],t.$refs={},t._provided=n?n._provided:Object.create(null),t._watcher=null,t._inactive=null,t._directInactive=!1,t._isMounted=!1,t._isDestroyed=!1,t._isBeingDestroyed=!1}(e),function(t){t._events=Object.create(null),t._hasHookEvent=!1;var e=t.$options._parentListeners;e&&Qe(t,e)}(e),function(t){t._vnode=null,t._staticTrees=null;var e=t.$options,n=t.$vnode=e._parentVnode,o=n&&n.context;t.$slots=pe(e._renderChildren,o),t.$scopedSlots=n?ve(t.$parent,n.data.scopedSlots,t.$slots):r,t._c=function(e,n,r,o){return $e(t,e,n,r,o,!1)},t.$createElement=function(e,n,r,o){return $e(t,e,n,r,o,!0)};var i=n&&n.data;Tt(t,"$attrs",i&&i.attrs||r,null,!0),Tt(t,"$listeners",e._parentListeners||r,null,!0)}(e),tn(e,"beforeCreate",void 0,!1),function(t){var e=hn(t.$options.inject,t);e&&(jt(!1),Object.keys(e).forEach((function(n){Tt(t,n,e[n])})),jt(!0))}(e),Fn(e),function(t){var e=t.$options.provide;if(e){var n=u(e)?e.call(t):e;if(!l(n))return;for(var r=qt(t),o=lt?Reflect.ownKeys(n):Object.keys(n),i=0;i1?A(n):n;for(var r=A(arguments,1),o='event handler for "'.concat(t,'"'),i=0,a=n.length;iparseInt(this.max)&&Xn(t,e[0],e,this._vnode),this.vnodeToCache=null}}},created:function(){this.cache=Object.create(null),this.keys=[]},destroyed:function(){for(var t in this.cache)Xn(this.cache,t,this.keys)},mounted:function(){var t=this;this.cacheVNode(),this.$watch("include",(function(e){Zn(t,(function(t){return Jn(e,t)}))})),this.$watch("exclude",(function(e){Zn(t,(function(t){return!Jn(e,t)}))}))},updated:function(){this.cacheVNode()},render:function(){var t=this.$slots.default,e=Ce(t),n=e&&e.componentOptions;if(n){var r=Qn(n),o=this.include,i=this.exclude;if(o&&(!r||!Jn(o,r))||i&&r&&Jn(i,r))return e;var a=this.cache,s=this.keys,c=null==e.key?n.Ctor.cid+(n.tag?"::".concat(n.tag):""):e.key;a[c]?(e.componentInstance=a[c].componentInstance,x(s,c),s.push(c)):(this.vnodeToCache=e,this.keyToCache=c),e.data.keepAlive=!0}return e||t&&t[0]}}};!function(t){var e={get:function(){return q}};Object.defineProperty(t,"config",e),t.util={warn:On,extend:T,mergeOptions:Pn,defineReactive:Tt},t.set=Lt,t.delete=Rt,t.nextTick=Fe,t.observable=function(t){return At(t),t},t.options=Object.create(null),z.forEach((function(e){t.options[e+"s"]=Object.create(null)})),t.options._base=t,T(t.options.components,tr),function(t){t.use=function(t){var e=this._installedPlugins||(this._installedPlugins=[]);if(e.indexOf(t)>-1)return this;var n=A(arguments,1);return n.unshift(this),u(t.install)?t.install.apply(t,n):u(t)&&t.apply(null,n),e.push(t),this}}(t),function(t){t.mixin=function(t){return this.options=Pn(this.options,t),this}}(t),Kn(t),function(t){z.forEach((function(e){t[e]=function(t,n){return n?("component"===e&&p(n)&&(n.name=n.name||t,n=this.options._base.extend(n)),"directive"===e&&u(n)&&(n={bind:n,update:n}),this.options[e+"s"][t]=n,n):this.options[e+"s"][t]}}))}(t)}(Gn),Object.defineProperty(Gn.prototype,"$isServer",{get:at}),Object.defineProperty(Gn.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(Gn,"FunctionalRenderContext",{value:vn}),Gn.version="2.7.16";var er=b("style,class"),nr=b("input,textarea,option,select,progress"),rr=b("contenteditable,draggable,spellcheck"),or=b("events,caret,typing,plaintext-only"),ir=b("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,truespeed,typemustmatch,visible"),ar="http://www.w3.org/1999/xlink",sr=function(t){return":"===t.charAt(5)&&"xlink"===t.slice(0,5)},cr=function(t){return sr(t)?t.slice(6,t.length):""},ur=function(t){return null==t||!1===t};function lr(t){for(var e=t.data,n=t,r=t;a(r.componentInstance);)(r=r.componentInstance._vnode)&&r.data&&(e=fr(r.data,e));for(;a(n=n.parent);)n&&n.data&&(e=fr(e,n.data));return function(t,e){if(a(t)||a(e))return pr(t,dr(e));return""}(e.staticClass,e.class)}function fr(t,e){return{staticClass:pr(t.staticClass,e.staticClass),class:a(t.class)?[t.class,e.class]:e.class}}function pr(t,e){return t?e?t+" "+e:t:e||""}function dr(t){return Array.isArray(t)?function(t){for(var e,n="",r=0,o=t.length;r-1?Dr(t,e,n):ir(e)?ur(n)?t.removeAttribute(e):(n="allowfullscreen"===e&&"EMBED"===t.tagName?"true":e,t.setAttribute(e,n)):rr(e)?t.setAttribute(e,function(t,e){return ur(e)||"false"===e?"false":"contenteditable"===t&&or(e)?e:"true"}(e,n)):sr(e)?ur(n)?t.removeAttributeNS(ar,cr(e)):t.setAttributeNS(ar,e,n):Dr(t,e,n)}function Dr(t,e,n){if(ur(n))t.removeAttribute(e);else{if(Z&&!X&&"TEXTAREA"===t.tagName&&"placeholder"===e&&""!==n&&!t.__ieph){var r=function(e){e.stopImmediatePropagation(),t.removeEventListener("input",r)};t.addEventListener("input",r),t.__ieph=!0}t.setAttribute(e,n)}}var Nr={create:Ir,update:Ir};function Fr(t,e){var n=e.elm,r=e.data,o=t.data;if(!(i(r.staticClass)&&i(r.class)&&(i(o)||i(o.staticClass)&&i(o.class)))){var s=lr(e),c=n._transitionClasses;a(c)&&(s=pr(s,dr(c))),s!==n._prevClass&&(n.setAttribute("class",s),n._prevClass=s)}}var Ur,zr={create:Fr,update:Fr};function Br(t,e,n){var r=Ur;return function o(){var i=e.apply(null,arguments);null!==i&&Hr(t,o,n,r)}}var qr=Ae&&!(nt&&Number(nt[1])<=53);function Vr(t,e,n,r){if(qr){var o=cn,i=e;e=i._wrapper=function(t){if(t.target===t.currentTarget||t.timeStamp>=o||t.timeStamp<=0||t.target.ownerDocument!==document)return i.apply(this,arguments)}}Ur.addEventListener(t,e,ot?{capture:n,passive:r}:n)}function Hr(t,e,n,r){(r||Ur).removeEventListener(t,e._wrapper||e,n)}function Wr(t,e){if(!i(t.data.on)||!i(e.data.on)){var n=e.data.on||{},r=t.data.on||{};Ur=e.elm||t.elm,function(t){if(a(t.__r)){var e=Z?"change":"input";t[e]=[].concat(t.__r,t[e]||[]),delete t.__r}a(t.__c)&&(t.change=[].concat(t.__c,t.change||[]),delete t.__c)}(n),Wt(n,r,Vr,Hr,Br,e.context),Ur=void 0}}var Gr,Kr={create:Wr,update:Wr,destroy:function(t){return Wr(t,Cr)}};function Qr(t,e){if(!i(t.data.domProps)||!i(e.data.domProps)){var n,r,o=e.elm,c=t.data.domProps||{},u=e.data.domProps||{};for(n in(a(u.__ob__)||s(u._v_attr_proxy))&&(u=e.data.domProps=T({},u)),c)n in u||(o[n]="");for(n in u){if(r=u[n],"textContent"===n||"innerHTML"===n){if(e.children&&(e.children.length=0),r===c[n])continue;1===o.childNodes.length&&o.removeChild(o.childNodes[0])}if("value"===n&&"PROGRESS"!==o.tagName){o._value=r;var l=i(r)?"":String(r);Jr(o,l)&&(o.value=l)}else if("innerHTML"===n&&mr(o.tagName)&&i(o.innerHTML)){(Gr=Gr||document.createElement("div")).innerHTML="".concat(r,"");for(var f=Gr.firstChild;o.firstChild;)o.removeChild(o.firstChild);for(;f.firstChild;)o.appendChild(f.firstChild)}else if(r!==c[n])try{o[n]=r}catch(t){}}}}function Jr(t,e){return!t.composing&&("OPTION"===t.tagName||function(t,e){var n=!0;try{n=document.activeElement!==t}catch(t){}return n&&t.value!==e}(t,e)||function(t,e){var n=t.value,r=t._vModifiers;if(a(r)){if(r.number)return g(n)!==g(e);if(r.trim)return n.trim()!==e.trim()}return n!==e}(t,e))}var Zr={create:Qr,update:Qr},Xr=C((function(t){var e={},n=/:(.+)/;return t.split(/;(?![^(]*\))/g).forEach((function(t){if(t){var r=t.split(n);r.length>1&&(e[r[0].trim()]=r[1].trim())}})),e}));function Yr(t){var e=to(t.style);return t.staticStyle?T(t.staticStyle,e):e}function to(t){return Array.isArray(t)?L(t):"string"==typeof t?Xr(t):t}var eo,no=/^--/,ro=/\s*!important$/,oo=function(t,e,n){if(no.test(e))t.style.setProperty(e,n);else if(ro.test(n))t.style.setProperty(E(e),n.replace(ro,""),"important");else{var r=ao(e);if(Array.isArray(n))for(var o=0,i=n.length;o-1?e.split(uo).forEach((function(e){return t.classList.add(e)})):t.classList.add(e);else{var n=" ".concat(t.getAttribute("class")||""," ");n.indexOf(" "+e+" ")<0&&t.setAttribute("class",(n+e).trim())}}function fo(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.split(uo).forEach((function(e){return t.classList.remove(e)})):t.classList.remove(e),t.classList.length||t.removeAttribute("class");else{for(var n=" ".concat(t.getAttribute("class")||""," "),r=" "+e+" ";n.indexOf(r)>=0;)n=n.replace(r," ");(n=n.trim())?t.setAttribute("class",n):t.removeAttribute("class")}}function po(t){if(t){if("object"==typeof t){var e={};return!1!==t.css&&T(e,ho(t.name||"v")),T(e,t),e}return"string"==typeof t?ho(t):void 0}}var ho=C((function(t){return{enterClass:"".concat(t,"-enter"),enterToClass:"".concat(t,"-enter-to"),enterActiveClass:"".concat(t,"-enter-active"),leaveClass:"".concat(t,"-leave"),leaveToClass:"".concat(t,"-leave-to"),leaveActiveClass:"".concat(t,"-leave-active")}})),vo=Q&&!X,mo="transition",yo="transitionend",go="animation",bo="animationend";vo&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(mo="WebkitTransition",yo="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(go="WebkitAnimation",bo="webkitAnimationEnd"));var _o=Q?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(t){return t()};function xo(t){_o((function(){_o(t)}))}function wo(t,e){var n=t._transitionClasses||(t._transitionClasses=[]);n.indexOf(e)<0&&(n.push(e),lo(t,e))}function Oo(t,e){t._transitionClasses&&x(t._transitionClasses,e),fo(t,e)}function Co(t,e,n){var r=ko(t,e),o=r.type,i=r.timeout,a=r.propCount;if(!o)return n();var s="transition"===o?yo:bo,c=0,u=function(){t.removeEventListener(s,l),n()},l=function(e){e.target===t&&++c>=a&&u()};setTimeout((function(){c0&&(n="transition",l=a,f=i.length):"animation"===e?u>0&&(n="animation",l=u,f=c.length):f=(n=(l=Math.max(a,u))>0?a>u?"transition":"animation":null)?"transition"===n?i.length:c.length:0,{type:n,timeout:l,propCount:f,hasTransform:"transition"===n&&$o.test(r[mo+"Property"])}}function So(t,e){for(;t.length1}function Lo(t,e){!0!==e.data.show&&Eo(e)}var Ro=function(t){var e,n,r={},u=t.modules,l=t.nodeOps;for(e=0;e<$r.length;++e)for(r[$r[e]]=[],n=0;nh?_(t,i(n[y+1])?null:n[y+1].elm,n,d,y,r):d>y&&w(e,f,h)}(f,v,y,n,u):a(y)?(a(t.text)&&l.setTextContent(f,""),_(f,null,y,0,y.length-1,n)):a(v)?w(v,0,v.length-1):a(t.text)&&l.setTextContent(f,""):t.text!==e.text&&l.setTextContent(f,e.text),a(h)&&a(d=h.hook)&&a(d=d.postpatch)&&d(t,e)}}}function k(t,e,n){if(s(n)&&a(t.parent))t.parent.data.pendingInsert=e;else for(var r=0;r-1,a.selected!==i&&(a.selected=i);else if(D(Fo(a),r))return void(t.selectedIndex!==s&&(t.selectedIndex=s));o||(t.selectedIndex=-1)}}function No(t,e){return e.every((function(e){return!D(e,t)}))}function Fo(t){return"_value"in t?t._value:t.value}function Uo(t){t.target.composing=!0}function zo(t){t.target.composing&&(t.target.composing=!1,Bo(t.target,"input"))}function Bo(t,e){var n=document.createEvent("HTMLEvents");n.initEvent(e,!0,!0),t.dispatchEvent(n)}function qo(t){return!t.componentInstance||t.data&&t.data.transition?t:qo(t.componentInstance._vnode)}var Vo={model:Io,show:{bind:function(t,e,n){var r=e.value,o=(n=qo(n)).data&&n.data.transition,i=t.__vOriginalDisplay="none"===t.style.display?"":t.style.display;r&&o?(n.data.show=!0,Eo(n,(function(){t.style.display=i}))):t.style.display=r?i:"none"},update:function(t,e,n){var r=e.value;!r!=!e.oldValue&&((n=qo(n)).data&&n.data.transition?(n.data.show=!0,r?Eo(n,(function(){t.style.display=t.__vOriginalDisplay})):Po(n,(function(){t.style.display="none"}))):t.style.display=r?t.__vOriginalDisplay:"none")},unbind:function(t,e,n,r,o){o||(t.style.display=t.__vOriginalDisplay)}}},Ho={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]};function Wo(t){var e=t&&t.componentOptions;return e&&e.Ctor.options.abstract?Wo(Ce(e.children)):t}function Go(t){var e={},n=t.$options;for(var r in n.propsData)e[r]=t[r];var o=n._parentListeners;for(var r in o)e[k(r)]=o[r];return e}function Ko(t,e){if(/\d-keep-alive$/.test(e.tag))return t("keep-alive",{props:e.componentOptions.propsData})}var Qo=function(t){return t.tag||he(t)},Jo=function(t){return"show"===t.name},Zo={name:"transition",props:Ho,abstract:!0,render:function(t){var e=this,n=this.$slots.default;if(n&&(n=n.filter(Qo)).length){0;var r=this.mode;0;var o=n[0];if(function(t){for(;t=t.parent;)if(t.data.transition)return!0}(this.$vnode))return o;var i=Wo(o);if(!i)return o;if(this._leaving)return Ko(t,o);var a="__transition-".concat(this._uid,"-");i.key=null==i.key?i.isComment?a+"comment":a+i.tag:c(i.key)?0===String(i.key).indexOf(a)?i.key:a+i.key:i.key;var s=(i.data||(i.data={})).transition=Go(this),u=this._vnode,l=Wo(u);if(i.data.directives&&i.data.directives.some(Jo)&&(i.data.show=!0),l&&l.data&&!function(t,e){return e.key===t.key&&e.tag===t.tag}(i,l)&&!he(l)&&(!l.componentInstance||!l.componentInstance._vnode.isComment)){var f=l.data.transition=T({},s);if("out-in"===r)return this._leaving=!0,Gt(f,"afterLeave",(function(){e._leaving=!1,e.$forceUpdate()})),Ko(t,o);if("in-out"===r){if(he(i))return u;var p,d=function(){p()};Gt(s,"afterEnter",d),Gt(s,"enterCancelled",d),Gt(f,"delayLeave",(function(t){p=t}))}}return o}}},Xo=T({tag:String,moveClass:String},Ho);function Yo(t){t.elm._moveCb&&t.elm._moveCb(),t.elm._enterCb&&t.elm._enterCb()}function ti(t){t.data.newPos=t.elm.getBoundingClientRect()}function ei(t){var e=t.data.pos,n=t.data.newPos,r=e.left-n.left,o=e.top-n.top;if(r||o){t.data.moved=!0;var i=t.elm.style;i.transform=i.WebkitTransform="translate(".concat(r,"px,").concat(o,"px)"),i.transitionDuration="0s"}}delete Xo.mode;var ni={Transition:Zo,TransitionGroup:{props:Xo,beforeMount:function(){var t=this,e=this._update;this._update=function(n,r){var o=Ze(t);t.__patch__(t._vnode,t.kept,!1,!0),t._vnode=t.kept,o(),e.call(t,n,r)}},render:function(t){for(var e=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,o=this.$slots.default||[],i=this.children=[],a=Go(this),s=0;s-1?gr[t]=e.constructor===window.HTMLUnknownElement||e.constructor===window.HTMLElement:gr[t]=/HTMLUnknownElement/.test(e.toString())},T(Gn.options.directives,Vo),T(Gn.options.components,ni),Gn.prototype.__patch__=Q?Ro:R,Gn.prototype.$mount=function(t,e){return function(t,e,n){var r;t.$el=e,t.$options.render||(t.$options.render=ht),tn(t,"beforeMount"),r=function(){t._update(t._render(),n)},new He(t,r,R,{before:function(){t._isMounted&&!t._isDestroyed&&tn(t,"beforeUpdate")}},!0),n=!1;var o=t._preWatchers;if(o)for(var i=0;i=0&&(e=t.slice(r),t=t.slice(0,r));var o=t.indexOf("?");return o>=0&&(n=t.slice(o+1),t=t.slice(0,o)),{path:t,query:n,hash:e}}(o.path||""),u=e&&e.path||"/",l=c.path?Oi(c.path,u,n||o.append):u,f=function(t,e,n){void 0===e&&(e={});var r,o=n||li;try{r=o(t||"")}catch(t){r={}}for(var i in e){var a=e[i];r[i]=Array.isArray(a)?a.map(ui):ui(a)}return r}(c.query,o.query,r&&r.options.parseQuery),p=o.hash||c.hash;return p&&"#"!==p.charAt(0)&&(p="#"+p),{_normalized:!0,path:l,query:f,hash:p}}var Vi,Hi=function(){},Wi={name:"RouterLink",props:{to:{type:[String,Object],required:!0},tag:{type:String,default:"a"},custom:Boolean,exact:Boolean,exactPath:Boolean,append:Boolean,replace:Boolean,activeClass:String,exactActiveClass:String,ariaCurrentValue:{type:String,default:"page"},event:{type:[String,Array],default:"click"}},render:function(t){var e=this,n=this.$router,r=this.$route,o=n.resolve(this.to,r,this.append),i=o.location,a=o.route,s=o.href,c={},u=n.options.linkActiveClass,l=n.options.linkExactActiveClass,f=null==u?"router-link-active":u,p=null==l?"router-link-exact-active":l,d=null==this.activeClass?f:this.activeClass,h=null==this.exactActiveClass?p:this.exactActiveClass,v=a.redirectedFrom?di(null,qi(a.redirectedFrom),null,n):a;c[h]=gi(r,v,this.exactPath),c[d]=this.exact||this.exactPath?c[h]:function(t,e){return 0===t.path.replace(pi,"/").indexOf(e.path.replace(pi,"/"))&&(!e.hash||t.hash===e.hash)&&function(t,e){for(var n in e)if(!(n in t))return!1;return!0}(t.query,e.query)}(r,v);var m=c[h]?this.ariaCurrentValue:null,y=function(t){Gi(t)&&(e.replace?n.replace(i,Hi):n.push(i,Hi))},g={click:Gi};Array.isArray(this.event)?this.event.forEach((function(t){g[t]=y})):g[this.event]=y;var b={class:c},_=!this.$scopedSlots.$hasNormal&&this.$scopedSlots.default&&this.$scopedSlots.default({href:s,route:a,navigate:y,isActive:c[d],isExactActive:c[h]});if(_){if(1===_.length)return _[0];if(_.length>1||!_.length)return 0===_.length?t():t("span",{},_)}if("a"===this.tag)b.on=g,b.attrs={href:s,"aria-current":m};else{var x=function t(e){var n;if(e)for(var r=0;r-1&&(s.params[p]=n.params[p]);return s.path=Bi(l.path,s.params),c(l,s,a)}if(s.path){s.params={};for(var d=0;d-1}function Ca(t,e){return Oa(t)&&t._isRouter&&(null==e||t.type===e)}function $a(t,e,n){var r=function(o){o>=t.length?n():t[o]?e(t[o],(function(){r(o+1)})):r(o+1)};r(0)}function ka(t){return function(e,n,r){var o=!1,i=0,a=null;Sa(t,(function(t,e,n,s){if("function"==typeof t&&void 0===t.cid){o=!0,i++;var c,u=Pa((function(e){var o;((o=e).__esModule||Ea&&"Module"===o[Symbol.toStringTag])&&(e=e.default),t.resolved="function"==typeof e?e:Vi.extend(e),n.components[s]=e,--i<=0&&r()})),l=Pa((function(t){var e="Failed to resolve async component "+s+": "+t;a||(a=Oa(t)?t:new Error(e),r(a))}));try{c=t(u,l)}catch(t){l(t)}if(c)if("function"==typeof c.then)c.then(u,l);else{var f=c.component;f&&"function"==typeof f.then&&f.then(u,l)}}})),o||r()}}function Sa(t,e){return ja(t.map((function(t){return Object.keys(t.components).map((function(n){return e(t.components[n],t.instances[n],t,n)}))})))}function ja(t){return Array.prototype.concat.apply([],t)}var Ea="function"==typeof Symbol&&"symbol"==typeof Symbol.toStringTag;function Pa(t){var e=!1;return function(){for(var n=[],r=arguments.length;r--;)n[r]=arguments[r];if(!e)return e=!0,t.apply(this,n)}}var Aa=function(t,e){this.router=t,this.base=function(t){if(!t)if(Ki){var e=document.querySelector("base");t=(t=e&&e.getAttribute("href")||"/").replace(/^https?:\/\/[^\/]+/,"")}else t="/";"/"!==t.charAt(0)&&(t="/"+t);return t.replace(/\/$/,"")}(e),this.current=vi,this.pending=null,this.ready=!1,this.readyCbs=[],this.readyErrorCbs=[],this.errorCbs=[],this.listeners=[]};function Ta(t,e,n,r){var o=Sa(t,(function(t,r,o,i){var a=function(t,e){"function"!=typeof t&&(t=Vi.extend(t));return t.options[e]}(t,e);if(a)return Array.isArray(a)?a.map((function(t){return n(t,r,o,i)})):n(a,r,o,i)}));return ja(r?o.reverse():o)}function La(t,e){if(e)return function(){return t.apply(e,arguments)}}Aa.prototype.listen=function(t){this.cb=t},Aa.prototype.onReady=function(t,e){this.ready?t():(this.readyCbs.push(t),e&&this.readyErrorCbs.push(e))},Aa.prototype.onError=function(t){this.errorCbs.push(t)},Aa.prototype.transitionTo=function(t,e,n){var r,o=this;try{r=this.router.match(t,this.current)}catch(t){throw this.errorCbs.forEach((function(e){e(t)})),t}var i=this.current;this.confirmTransition(r,(function(){o.updateRoute(r),e&&e(r),o.ensureURL(),o.router.afterHooks.forEach((function(t){t&&t(r,i)})),o.ready||(o.ready=!0,o.readyCbs.forEach((function(t){t(r)})))}),(function(t){n&&n(t),t&&!o.ready&&(Ca(t,ga.redirected)&&i===vi||(o.ready=!0,o.readyErrorCbs.forEach((function(e){e(t)}))))}))},Aa.prototype.confirmTransition=function(t,e,n){var r=this,o=this.current;this.pending=t;var i,a,s=function(t){!Ca(t)&&Oa(t)&&(r.errorCbs.length?r.errorCbs.forEach((function(e){e(t)})):console.error(t)),n&&n(t)},c=t.matched.length-1,u=o.matched.length-1;if(gi(t,o)&&c===u&&t.matched[c]===o.matched[u])return this.ensureURL(),t.hash&&aa(this.router,o,t,!1),s(((a=xa(i=o,t,ga.duplicated,'Avoided redundant navigation to current location: "'+i.fullPath+'".')).name="NavigationDuplicated",a));var l=function(t,e){var n,r=Math.max(t.length,e.length);for(n=0;n0)){var e=this.router,n=e.options.scrollBehavior,r=va&&n;r&&this.listeners.push(ia());var o=function(){var n=t.current,o=Ia(t.base);t.current===vi&&o===t._startLocation||t.transitionTo(o,(function(t){r&&aa(e,t,n,!0)}))};window.addEventListener("popstate",o),this.listeners.push((function(){window.removeEventListener("popstate",o)}))}},e.prototype.go=function(t){window.history.go(t)},e.prototype.push=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){ma(Ci(r.base+t.fullPath)),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){ya(Ci(r.base+t.fullPath)),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.ensureURL=function(t){if(Ia(this.base)!==this.current.fullPath){var e=Ci(this.base+this.current.fullPath);t?ma(e):ya(e)}},e.prototype.getCurrentLocation=function(){return Ia(this.base)},e}(Aa);function Ia(t){var e=window.location.pathname,n=e.toLowerCase(),r=t.toLowerCase();return!t||n!==r&&0!==n.indexOf(Ci(r+"/"))||(e=e.slice(t.length)),(e||"/")+window.location.search+window.location.hash}var Ma=function(t){function e(e,n,r){t.call(this,e,n),r&&function(t){var e=Ia(t);if(!/^\/#/.test(e))return window.location.replace(Ci(t+"/#"+e)),!0}(this.base)||Da()}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.setupListeners=function(){var t=this;if(!(this.listeners.length>0)){var e=this.router.options.scrollBehavior,n=va&&e;n&&this.listeners.push(ia());var r=function(){var e=t.current;Da()&&t.transitionTo(Na(),(function(r){n&&aa(t.router,r,e,!0),va||za(r.fullPath)}))},o=va?"popstate":"hashchange";window.addEventListener(o,r),this.listeners.push((function(){window.removeEventListener(o,r)}))}},e.prototype.push=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){Ua(t.fullPath),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){za(t.fullPath),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.go=function(t){window.history.go(t)},e.prototype.ensureURL=function(t){var e=this.current.fullPath;Na()!==e&&(t?Ua(e):za(e))},e.prototype.getCurrentLocation=function(){return Na()},e}(Aa);function Da(){var t=Na();return"/"===t.charAt(0)||(za("/"+t),!1)}function Na(){var t=window.location.href,e=t.indexOf("#");return e<0?"":t=t.slice(e+1)}function Fa(t){var e=window.location.href,n=e.indexOf("#");return(n>=0?e.slice(0,n):e)+"#"+t}function Ua(t){va?ma(Fa(t)):window.location.hash=t}function za(t){va?ya(Fa(t)):window.location.replace(Fa(t))}var Ba=function(t){function e(e,n){t.call(this,e,n),this.stack=[],this.index=-1}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.push=function(t,e,n){var r=this;this.transitionTo(t,(function(t){r.stack=r.stack.slice(0,r.index+1).concat(t),r.index++,e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var r=this;this.transitionTo(t,(function(t){r.stack=r.stack.slice(0,r.index).concat(t),e&&e(t)}),n)},e.prototype.go=function(t){var e=this,n=this.index+t;if(!(n<0||n>=this.stack.length)){var r=this.stack[n];this.confirmTransition(r,(function(){var t=e.current;e.index=n,e.updateRoute(r),e.router.afterHooks.forEach((function(e){e&&e(r,t)}))}),(function(t){Ca(t,ga.duplicated)&&(e.index=n)}))}},e.prototype.getCurrentLocation=function(){var t=this.stack[this.stack.length-1];return t?t.fullPath:"/"},e.prototype.ensureURL=function(){},e}(Aa),qa=function(t){void 0===t&&(t={}),this.app=null,this.apps=[],this.options=t,this.beforeHooks=[],this.resolveHooks=[],this.afterHooks=[],this.matcher=Zi(t.routes||[],this);var e=t.mode||"hash";switch(this.fallback="history"===e&&!va&&!1!==t.fallback,this.fallback&&(e="hash"),Ki||(e="abstract"),this.mode=e,e){case"history":this.history=new Ra(this,t.base);break;case"hash":this.history=new Ma(this,t.base,this.fallback);break;case"abstract":this.history=new Ba(this,t.base);break;default:0}},Va={currentRoute:{configurable:!0}};qa.prototype.match=function(t,e,n){return this.matcher.match(t,e,n)},Va.currentRoute.get=function(){return this.history&&this.history.current},qa.prototype.init=function(t){var e=this;if(this.apps.push(t),t.$once("hook:destroyed",(function(){var n=e.apps.indexOf(t);n>-1&&e.apps.splice(n,1),e.app===t&&(e.app=e.apps[0]||null),e.app||e.history.teardown()})),!this.app){this.app=t;var n=this.history;if(n instanceof Ra||n instanceof Ma){var r=function(t){n.setupListeners(),function(t){var r=n.current,o=e.options.scrollBehavior;va&&o&&"fullPath"in t&&aa(e,t,r,!1)}(t)};n.transitionTo(n.getCurrentLocation(),r,r)}n.listen((function(t){e.apps.forEach((function(e){e._route=t}))}))}},qa.prototype.beforeEach=function(t){return Wa(this.beforeHooks,t)},qa.prototype.beforeResolve=function(t){return Wa(this.resolveHooks,t)},qa.prototype.afterEach=function(t){return Wa(this.afterHooks,t)},qa.prototype.onReady=function(t,e){this.history.onReady(t,e)},qa.prototype.onError=function(t){this.history.onError(t)},qa.prototype.push=function(t,e,n){var r=this;if(!e&&!n&&"undefined"!=typeof Promise)return new Promise((function(e,n){r.history.push(t,e,n)}));this.history.push(t,e,n)},qa.prototype.replace=function(t,e,n){var r=this;if(!e&&!n&&"undefined"!=typeof Promise)return new Promise((function(e,n){r.history.replace(t,e,n)}));this.history.replace(t,e,n)},qa.prototype.go=function(t){this.history.go(t)},qa.prototype.back=function(){this.go(-1)},qa.prototype.forward=function(){this.go(1)},qa.prototype.getMatchedComponents=function(t){var e=t?t.matched?t:this.resolve(t).route:this.currentRoute;return e?[].concat.apply([],e.matched.map((function(t){return Object.keys(t.components).map((function(e){return t.components[e]}))}))):[]},qa.prototype.resolve=function(t,e,n){var r=qi(t,e=e||this.history.current,n,this),o=this.match(r,e),i=o.redirectedFrom||o.fullPath;return{location:r,route:o,href:function(t,e,n){var r="hash"===n?"#"+e:e;return t?Ci(t+"/"+r):r}(this.history.base,i,this.mode),normalizedTo:r,resolved:o}},qa.prototype.getRoutes=function(){return this.matcher.getRoutes()},qa.prototype.addRoute=function(t,e){this.matcher.addRoute(t,e),this.history.current!==vi&&this.history.transitionTo(this.history.getCurrentLocation())},qa.prototype.addRoutes=function(t){this.matcher.addRoutes(t),this.history.current!==vi&&this.history.transitionTo(this.history.getCurrentLocation())},Object.defineProperties(qa.prototype,Va);var Ha=qa;function Wa(t,e){return t.push(e),function(){var n=t.indexOf(e);n>-1&&t.splice(n,1)}}qa.install=function t(e){if(!t.installed||Vi!==e){t.installed=!0,Vi=e;var n=function(t){return void 0!==t},r=function(t,e){var r=t.$options._parentVnode;n(r)&&n(r=r.data)&&n(r=r.registerRouteInstance)&&r(t,e)};e.mixin({beforeCreate:function(){n(this.$options.router)?(this._routerRoot=this,this._router=this.$options.router,this._router.init(this),e.util.defineReactive(this,"_route",this._router.history.current)):this._routerRoot=this.$parent&&this.$parent._routerRoot||this,r(this,this)},destroyed:function(){r(this)}}),Object.defineProperty(e.prototype,"$router",{get:function(){return this._routerRoot._router}}),Object.defineProperty(e.prototype,"$route",{get:function(){return this._routerRoot._route}}),e.component("RouterView",xi),e.component("RouterLink",Wi);var o=e.config.optionMergeStrategies;o.beforeRouteEnter=o.beforeRouteLeave=o.beforeRouteUpdate=o.created}},qa.version="3.6.5",qa.isNavigationFailure=Ca,qa.NavigationFailureType=ga,qa.START_LOCATION=vi,Ki&&window.Vue&&window.Vue.use(qa);n(97);n(124),n(90);var Ga={"components/AlgoliaSearchBox":()=>Promise.all([n.e(0),n.e(13)]).then(n.bind(null,298)),"components/DropdownLink":()=>Promise.all([n.e(0),n.e(14)]).then(n.bind(null,255)),"components/DropdownTransition":()=>Promise.all([n.e(0),n.e(19)]).then(n.bind(null,243)),"components/Home":()=>Promise.all([n.e(0),n.e(16)]).then(n.bind(null,281)),"components/NavLink":()=>n.e(21).then(n.bind(null,242)),"components/NavLinks":()=>Promise.all([n.e(0),n.e(12)]).then(n.bind(null,266)),"components/Navbar":()=>Promise.all([n.e(0),n.e(1)]).then(n.bind(null,295)),"components/Page":()=>Promise.all([n.e(0),n.e(11)]).then(n.bind(null,282)),"components/PageEdit":()=>Promise.all([n.e(0),n.e(17)]).then(n.bind(null,268)),"components/PageNav":()=>Promise.all([n.e(0),n.e(15)]).then(n.bind(null,269)),"components/Sidebar":()=>Promise.all([n.e(0),n.e(10)]).then(n.bind(null,283)),"components/SidebarButton":()=>Promise.all([n.e(0),n.e(20)]).then(n.bind(null,284)),"components/SidebarGroup":()=>Promise.all([n.e(0),n.e(3)]).then(n.bind(null,267)),"components/SidebarLink":()=>Promise.all([n.e(0),n.e(18)]).then(n.bind(null,256)),"components/SidebarLinks":()=>Promise.all([n.e(0),n.e(3)]).then(n.bind(null,254)),"global-components/Badge":()=>Promise.all([n.e(0),n.e(4)]).then(n.bind(null,303)),"global-components/CodeBlock":()=>Promise.all([n.e(0),n.e(5)]).then(n.bind(null,299)),"global-components/CodeGroup":()=>Promise.all([n.e(0),n.e(6)]).then(n.bind(null,300)),"layouts/404":()=>n.e(7).then(n.bind(null,301)),"layouts/Layout":()=>Promise.all([n.e(0),n.e(1),n.e(2)]).then(n.bind(null,302)),NotFound:()=>n.e(7).then(n.bind(null,301)),Layout:()=>Promise.all([n.e(0),n.e(1),n.e(2)]).then(n.bind(null,302))},Ka={"v-3c88bbf2":()=>n.e(22).then(n.bind(null,304)),"v-0decf914":()=>n.e(23).then(n.bind(null,305)),"v-d7e5bcfc":()=>n.e(24).then(n.bind(null,306)),"v-c864372e":()=>n.e(25).then(n.bind(null,307)),"v-23f0ba6e":()=>n.e(27).then(n.bind(null,308)),"v-102beaee":()=>n.e(26).then(n.bind(null,309)),"v-4419f5c9":()=>n.e(28).then(n.bind(null,310)),"v-05e5796e":()=>n.e(29).then(n.bind(null,311)),"v-6d148503":()=>n.e(30).then(n.bind(null,312)),"v-41c3bc69":()=>n.e(31).then(n.bind(null,313)),"v-2bf9c0ae":()=>n.e(32).then(n.bind(null,314)),"v-1c00b5c9":()=>n.e(33).then(n.bind(null,315)),"v-56e4d50b":()=>n.e(34).then(n.bind(null,316)),"v-4f917bd3":()=>n.e(35).then(n.bind(null,317)),"v-87b4d6ae":()=>n.e(36).then(n.bind(null,318)),"v-7bafdcee":()=>n.e(37).then(n.bind(null,319)),"v-6abbdcee":()=>n.e(38).then(n.bind(null,320)),"v-ded899ca":()=>n.e(39).then(n.bind(null,321)),"v-09883f07":()=>n.e(40).then(n.bind(null,322)),"v-40b685e4":()=>n.e(41).then(n.bind(null,323)),"v-a971ed74":()=>n.e(42).then(n.bind(null,324))};function Qa(t){const e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}const Ja=/-(\w)/g,Za=Qa(t=>t.replace(Ja,(t,e)=>e?e.toUpperCase():"")),Xa=/\B([A-Z])/g,Ya=Qa(t=>t.replace(Xa,"-$1").toLowerCase()),ts=Qa(t=>t.charAt(0).toUpperCase()+t.slice(1));function es(t,e){if(!e)return;if(t(e))return t(e);return e.includes("-")?t(ts(Za(e))):t(ts(e))||t(Ya(e))}const ns=Object.assign({},Ga,Ka),rs=t=>ns[t],os=t=>Ka[t],is=t=>Ga[t],as=t=>Gn.component(t);function ss(t){return es(os,t)}function cs(t){return es(is,t)}function us(t){return es(rs,t)}function ls(t){return es(as,t)}function fs(...t){return Promise.all(t.filter(t=>t).map(async t=>{if(!ls(t)&&us(t)){const e=await us(t)();Gn.component(t,e.default)}}))}function ps(t,e){"undefined"!=typeof window&&window.__VUEPRESS__&&(window.__VUEPRESS__[t]=e)}var ds=n(87),hs=n.n(ds),vs=n(88),ms=n.n(vs),ys={created(){if(this.siteMeta=this.$site.headTags.filter(([t])=>"meta"===t).map(([t,e])=>e),this.$ssrContext){const e=this.getMergedMetaTags();this.$ssrContext.title=this.$title,this.$ssrContext.lang=this.$lang,this.$ssrContext.pageMeta=(t=e)?t.map(t=>{let e="{e+=` ${n}="${ms()(t[n])}"`}),e+">"}).join("\n "):"",this.$ssrContext.canonicalLink=bs(this.$canonicalUrl)}var t},mounted(){this.currentMetaTags=[...document.querySelectorAll("meta")],this.updateMeta(),this.updateCanonicalLink()},methods:{updateMeta(){document.title=this.$title,document.documentElement.lang=this.$lang;const t=this.getMergedMetaTags();this.currentMetaTags=_s(t,this.currentMetaTags)},getMergedMetaTags(){const t=this.$page.frontmatter.meta||[];return hs()([{name:"description",content:this.$description}],t,this.siteMeta,xs)},updateCanonicalLink(){gs(),this.$canonicalUrl&&document.head.insertAdjacentHTML("beforeend",bs(this.$canonicalUrl))}},watch:{$page(){this.updateMeta(),this.updateCanonicalLink()}},beforeDestroy(){_s(null,this.currentMetaTags),gs()}};function gs(){const t=document.querySelector("link[rel='canonical']");t&&t.remove()}function bs(t=""){return t?``:""}function _s(t,e){if(e&&[...e].filter(t=>t.parentNode===document.head).forEach(t=>document.head.removeChild(t)),t)return t.map(t=>{const e=document.createElement("meta");return Object.keys(t).forEach(n=>{e.setAttribute(n,t[n])}),document.head.appendChild(e),e})}function xs(t){for(const e of["name","property","itemprop"])if(t.hasOwnProperty(e))return t[e]+e;return JSON.stringify(t)}var ws=n(89),Os={mounted(){window.addEventListener("scroll",this.onScroll)},methods:{onScroll:n.n(ws)()((function(){this.setActiveHash()}),300),setActiveHash(){const t=[].slice.call(document.querySelectorAll(".sidebar-link")),e=[].slice.call(document.querySelectorAll(".header-anchor")).filter(e=>t.some(t=>t.hash===e.hash)),n=Math.max(window.pageYOffset,document.documentElement.scrollTop,document.body.scrollTop),r=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),o=window.innerHeight+n;for(let t=0;t=i.parentElement.offsetTop+10&&(!a||n{this.$nextTick(()=>{this.$vuepress.$set("disableScrollBehavior",!1)})})}}}},beforeDestroy(){window.removeEventListener("scroll",this.onScroll)}},Cs=n(22),$s=n.n(Cs),ks=[ys,Os,{mounted(){$s.a.configure({showSpinner:!1}),this.$router.beforeEach((t,e,n)=>{t.path===e.path||Gn.component(t.name)||$s.a.start(),n()}),this.$router.afterEach(()=>{$s.a.done(),this.isSidebarOpen=!1})}}],Ss={name:"GlobalLayout",computed:{layout(){const t=this.getLayout();return ps("layout",t),Gn.component(t)}},methods:{getLayout(){if(this.$page.path){const t=this.$page.frontmatter.layout;return t&&(this.$vuepress.getLayoutAsyncComponent(t)||this.$vuepress.getVueComponent(t))?t:"Layout"}return"NotFound"}}},js=n(14),Es=Object(js.a)(Ss,(function(){return(0,this._self._c)(this.layout,{tag:"component"})}),[],!1,null,null,null).exports;!function(t,e,n){switch(e){case"components":t[e]||(t[e]={}),Object.assign(t[e],n);break;case"mixins":t[e]||(t[e]=[]),t[e].push(...n);break;default:throw new Error("Unknown option name.")}}(Es,"mixins",ks);const Ps=[{name:"v-3c88bbf2",path:"/",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-3c88bbf2").then(n)}},{path:"/index.html",redirect:"/"},{name:"v-0decf914",path:"/about/",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-0decf914").then(n)}},{path:"/about/index.html",redirect:"/about/"},{name:"v-d7e5bcfc",path:"/docs/",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-d7e5bcfc").then(n)}},{path:"/docs/index.html",redirect:"/docs/"},{name:"v-c864372e",path:"/docs/adapters.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-c864372e").then(n)}},{name:"v-23f0ba6e",path:"/docs/client.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-23f0ba6e").then(n)}},{name:"v-102beaee",path:"/docs/client-codegen.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-102beaee").then(n)}},{name:"v-4419f5c9",path:"/docs/examples.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-4419f5c9").then(n)}},{name:"v-05e5796e",path:"/docs/federation.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-05e5796e").then(n)}},{name:"v-6d148503",path:"/docs/interop.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-6d148503").then(n)}},{name:"v-41c3bc69",path:"/docs/laminext.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-41c3bc69").then(n)}},{name:"v-2bf9c0ae",path:"/docs/middleware.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-2bf9c0ae").then(n)}},{name:"v-1c00b5c9",path:"/docs/optimization.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-1c00b5c9").then(n)}},{name:"v-56e4d50b",path:"/docs/relay-connections.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-56e4d50b").then(n)}},{name:"v-4f917bd3",path:"/docs/schema-comparison.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-4f917bd3").then(n)}},{name:"v-87b4d6ae",path:"/docs/schema-reporting.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-87b4d6ae").then(n)}},{name:"v-7bafdcee",path:"/docs/schema.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-7bafdcee").then(n)}},{name:"v-6abbdcee",path:"/docs/server-codegen.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-6abbdcee").then(n)}},{name:"v-ded899ca",path:"/docs/stitching.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-ded899ca").then(n)}},{name:"v-09883f07",path:"/docs/tools.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-09883f07").then(n)}},{name:"v-40b685e4",path:"/faq/",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-40b685e4").then(n)}},{path:"/faq/index.html",redirect:"/faq/"},{name:"v-a971ed74",path:"/resources/",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-a971ed74").then(n)}},{path:"/resources/index.html",redirect:"/resources/"},{path:"*",component:Es}],As={title:"",description:"",base:"/caliban/",headTags:[["link",{rel:"icon",href:"/caliban/caliban.png"}]],pages:[{title:"Home",frontmatter:{home:!0,heroImage:"/caliban.svg",actionText:"Get Started →",actionLink:"/docs/",features:[{title:"High performance",details:"While all public interfaces are pure and immutable, the library's internals are optimized for speed."},{title:"Minimal boilerplate",details:"No need to manually define schemas for every type in your API. Let the compiler handle the tedious work."},{title:"Excellent interoperability",details:"Out-of-the-box support for major HTTP server libraries, effect types, JSON libraries, and more."}]},regularPath:"/",relativePath:"README.md",key:"v-3c88bbf2",path:"/"},{title:"About",frontmatter:{},regularPath:"/about/",relativePath:"about/README.md",key:"v-0decf914",path:"/about/"},{title:"Getting Started",frontmatter:{},regularPath:"/docs/",relativePath:"docs/README.md",key:"v-d7e5bcfc",path:"/docs/",headers:[{level:2,title:"A simple schema",slug:"a-simple-schema"},{level:2,title:"Serving over HTTP",slug:"serving-over-http"},{level:2,title:"Interop with 3rd-party libraries",slug:"interop-with-3rd-party-libraries"},{level:2,title:"Where to go next?",slug:"where-to-go-next"}]},{title:"Http Adapters",frontmatter:{},regularPath:"/docs/adapters.html",relativePath:"docs/adapters.md",key:"v-c864372e",path:"/docs/adapters.html",headers:[{level:2,title:"Built-in tapir adapters",slug:"built-in-tapir-adapters"},{level:2,title:"Make your own adapter",slug:"make-your-own-adapter"},{level:2,title:"High-performance QuickAdapter",slug:"high-performance-quickadapter"},{level:3,title:"Usage",slug:"usage"},{level:3,title:"Customization",slug:"customization"}]},{title:"Getting Started",frontmatter:{},regularPath:"/docs/client.html",relativePath:"docs/client.md",key:"v-23f0ba6e",path:"/docs/client.html",headers:[{level:2,title:"Dependencies",slug:"dependencies"},{level:2,title:"Code generation",slug:"code-generation"},{level:2,title:"Query building",slug:"query-building"},{level:2,title:"Request execution",slug:"request-execution"}]},{title:"Code Generation",frontmatter:{},regularPath:"/docs/client-codegen.html",relativePath:"docs/client-codegen.md",key:"v-102beaee",path:"/docs/client-codegen.html",headers:[{level:2,title:"CalibanPlugin",slug:"calibanplugin"},{level:3,title:"From a schema file",slug:"from-a-schema-file"},{level:3,title:"From a server URL",slug:"from-a-server-url"},{level:3,title:"Generation settings",slug:"generation-settings"},{level:3,title:"Manual generation",slug:"manual-generation"},{level:2,title:"CompileTimeCalibanPlugin",slug:"compiletimecalibanplugin"},{level:3,title:"Server side configuration",slug:"server-side-configuration"},{level:3,title:"Client side configuration",slug:"client-side-configuration"},{level:3,title:"Additional information about CompileTimeCalibanPlugin",slug:"additional-information-about-compiletimecalibanplugin"}]},{title:"Examples",frontmatter:{},regularPath:"/docs/examples.html",relativePath:"docs/examples.md",key:"v-4419f5c9",path:"/docs/examples.html"},{title:"Federation",frontmatter:{},regularPath:"/docs/federation.html",relativePath:"docs/federation.md",key:"v-05e5796e",path:"/docs/federation.html",headers:[{level:2,title:"Dependencies",slug:"dependencies"},{level:2,title:"Federating",slug:"federating"},{level:2,title:"Tracing",slug:"tracing"},{level:2,title:"Federation V2",slug:"federation-v2"},{level:3,title:"Customizing Federation",slug:"customizing-federation"}]},{title:"Interop with other libraries",frontmatter:{},regularPath:"/docs/interop.html",relativePath:"docs/interop.md",key:"v-6d148503",path:"/docs/interop.html",headers:[{level:2,title:"Cats Effect",slug:"cats-effect"},{level:2,title:"Monix (only with cats-effect 2.x)",slug:"monix-only-with-cats-effect-2-x"},{level:2,title:"Tapir",slug:"tapir"},{level:3,title:"GraphQL restrictions",slug:"graphql-restrictions"}]},{title:"Laminext Integration",frontmatter:{},regularPath:"/docs/laminext.html",relativePath:"docs/laminext.md",key:"v-41c3bc69",path:"/docs/laminext.html"},{title:"Middleware",frontmatter:{},regularPath:"/docs/middleware.html",relativePath:"docs/middleware.md",key:"v-2bf9c0ae",path:"/docs/middleware.html",headers:[{level:2,title:"Wrapper types",slug:"wrapper-types"},{level:2,title:"Pre-defined wrappers",slug:"pre-defined-wrappers"},{level:2,title:"Wrapping the interpreter",slug:"wrapping-the-interpreter"},{level:2,title:"Customizing error responses",slug:"customizing-error-responses"},{level:2,title:"Wrapping the GraphQL",slug:"wrapping-the-graphql"},{level:2,title:"Cost Estimation",slug:"cost-estimation"},{level:2,title:"OpenTelemetry Tracing",slug:"opentelemetry-tracing"}]},{title:"Query optimization",frontmatter:{},regularPath:"/docs/optimization.html",relativePath:"docs/optimization.md",key:"v-1c00b5c9",path:"/docs/optimization.html",headers:[{level:2,title:"Introducing ZQuery",slug:"introducing-zquery"},{level:2,title:"Building a DataSource",slug:"building-a-datasource"},{level:2,title:"ZQuery constructors and operators",slug:"zquery-constructors-and-operators"},{level:2,title:"Using ZQuery with Caliban",slug:"using-zquery-with-caliban"},{level:2,title:"Using field metadata",slug:"using-field-metadata"},{level:2,title:"@defer support (experimental)",slug:"defer-support-experimental"},{level:3,title:"Usage",slug:"usage"}]},{title:"Relay Connections",frontmatter:{},regularPath:"/docs/relay-connections.html",relativePath:"docs/relay-connections.md",key:"v-56e4d50b",path:"/docs/relay-connections.html",headers:[{level:2,title:"Cursors",slug:"cursors"}]},{title:"Schema comparison",frontmatter:{},regularPath:"/docs/schema-comparison.html",relativePath:"docs/schema-comparison.md",key:"v-4f917bd3",path:"/docs/schema-comparison.html"},{title:"Schema Reporting",frontmatter:{},regularPath:"/docs/schema-reporting.html",relativePath:"docs/schema-reporting.md",key:"v-87b4d6ae",path:"/docs/schema-reporting.html"},{title:"Schema generation",frontmatter:{},regularPath:"/docs/schema.html",relativePath:"docs/schema.md",key:"v-7bafdcee",path:"/docs/schema.html",headers:[{level:2,title:"Enums, unions, interfaces",slug:"enums-unions-interfaces"},{level:2,title:"Case classes and sealed traits",slug:"case-classes-and-sealed-traits"},{level:3,title:"Auto derivation",slug:"auto-derivation"},{level:3,title:"Semi-auto derivation",slug:"semi-auto-derivation"},{level:3,title:"Combining auto and semi-auto derivation",slug:"combining-auto-and-semi-auto-derivation"},{level:3,title:"Deriving fields from case class methods (Scala 3 only)",slug:"deriving-fields-from-case-class-methods-scala-3-only"},{level:2,title:"Arguments",slug:"arguments"},{level:3,title:"Input objects",slug:"input-objects"},{level:3,title:"@oneOf input objects",slug:"oneof-input-objects"},{level:2,title:"Custom types",slug:"custom-types"},{level:2,title:"Effects",slug:"effects"},{level:2,title:"Subscriptions",slug:"subscriptions"},{level:2,title:"Annotations",slug:"annotations"},{level:2,title:"Java 8 Time types",slug:"java-8-time-types"},{level:2,title:"Using features that are disabled by default",slug:"using-features-that-are-disabled-by-default"},{level:3,title:"SemanticNonNull support",slug:"semanticnonnull-support"},{level:2,title:"Building Schemas by hand",slug:"building-schemas-by-hand"},{level:2,title:"Schema transformations",slug:"schema-transformations"}]},{title:"Code generation",frontmatter:{},regularPath:"/docs/server-codegen.html",relativePath:"docs/server-codegen.md",key:"v-6abbdcee",path:"/docs/server-codegen.html",headers:[{level:2,title:"Options",slug:"options"},{level:2,title:"Lazy evaluation",slug:"lazy-evaluation"},{level:2,title:"Newtype declaration",slug:"newtype-declaration"}]},{title:"Stitching",frontmatter:{},regularPath:"/docs/stitching.html",relativePath:"docs/stitching.md",key:"v-ded899ca",path:"/docs/stitching.html",headers:[{level:2,title:"Dependencies",slug:"dependencies"},{level:2,title:"Stitching in Action",slug:"stitching-in-action"},{level:2,title:"Things not yet supported",slug:"things-not-yet-supported"}]},{title:"Getting Started",frontmatter:{},regularPath:"/docs/tools.html",relativePath:"docs/tools.md",key:"v-09883f07",path:"/docs/tools.html",headers:[{level:2,title:"Dependency",slug:"dependency"}]},{title:"FAQ",frontmatter:{},regularPath:"/faq/",relativePath:"faq/README.md",key:"v-40b685e4",path:"/faq/",headers:[{level:3,title:"I don't know where to start 😥",slug:"i-don-t-know-where-to-start-😥"},{level:3,title:"I'm getting a compilation error saying a Schema is missing, but I don't know which one.",slug:"i-m-getting-a-compilation-error-saying-a-schema-is-missing-but-i-don-t-know-which-one"},{level:3,title:"I want to use Caliban, but I use Cats Effect / Monix instead of ZIO.",slug:"i-want-to-use-caliban-but-i-use-cats-effect-monix-instead-of-zio"},{level:3,title:'My query fails with an "Effect failure" error. How can I get more details?',slug:"my-query-fails-with-an-effect-failure-error-how-can-i-get-more-details"},{level:3,title:"I have more than 22 fields in my Query, I can't create a case class for it.",slug:"i-have-more-than-22-fields-in-my-query-i-can-t-create-a-case-class-for-it"},{level:3,title:"How to deal with authentication/authorization?",slug:"how-to-deal-with-authentication-authorization"},{level:3,title:"I have 2 case classes with the same name (different packages). How to avoid conflicts?",slug:"i-have-2-case-classes-with-the-same-name-different-packages-how-to-avoid-conflicts"},{level:3,title:"The auto-generated schema shows a field is nullable, but I want it non-nullable instead.",slug:"the-auto-generated-schema-shows-a-field-is-nullable-but-i-want-it-non-nullable-instead"},{level:3,title:"Can I use a union as input?",slug:"can-i-use-a-union-as-input"},{level:3,title:"How to deal with recursive types?",slug:"how-to-deal-with-recursive-types"},{level:3,title:'I\'m getting a "Method too large" compiler error.',slug:"i-m-getting-a-method-too-large-compiler-error"},{level:3,title:"How can I define a Schema for a Java enum?",slug:"how-can-i-define-a-schema-for-a-java-enum"},{level:3,title:"I don't want to use Throwable as my error type",slug:"i-don-t-want-to-use-throwable-as-my-error-type"},{level:3,title:"My interface is missing from the schema",slug:"my-interface-is-missing-from-the-schema"},{level:3,title:"Can I check that a GraphQL query is valid at compile-time?",slug:"can-i-check-that-a-graphql-query-is-valid-at-compile-time"}]},{title:"Resources",frontmatter:{},regularPath:"/resources/",relativePath:"resources/README.md",key:"v-a971ed74",path:"/resources/",headers:[{level:2,title:"Talks",slug:"talks"},{level:2,title:"Blog Articles",slug:"blog-articles"},{level:2,title:"Related Projects",slug:"related-projects"}]}],themeConfig:{logo:"/caliban.svg",locales:{"/":{selectText:"Language",label:"English",nav:[{text:"Documentation",link:"/docs/"},{text:"Resources",link:"/resources/"},{text:"FAQ",link:"/faq/"},{text:"About",link:"/about/"},{text:"Github",link:"https://github.com/ghostdogpr/caliban"},{text:"Scaladoc",link:"https://javadoc.io/doc/com.github.ghostdogpr/caliban_3/"}],sidebar:{"/docs/":[{title:"Caliban Server",collapsable:!0,sidebarDepth:2,children:["","schema","server-codegen","adapters","middleware","optimization","interop","federation","relay-connections","schema-reporting"]},{title:"Caliban Client",collapsable:!0,sidebarDepth:2,children:["client","client-codegen","laminext"]},{title:"Caliban Tools",collapsable:!0,sidebarDepth:2,children:["tools","stitching","schema-comparison"]},{title:"Examples",path:"examples"}]}}}},locales:{"/":{lang:"en-US",title:"Caliban",description:"Functional GraphQL library for Scala",path:"/"}}};n(235);Gn.component("Badge",()=>Promise.all([n.e(0),n.e(4)]).then(n.bind(null,303))),Gn.component("CodeBlock",()=>Promise.all([n.e(0),n.e(5)]).then(n.bind(null,299))),Gn.component("CodeGroup",()=>Promise.all([n.e(0),n.e(6)]).then(n.bind(null,300)));n(236);var Ts=[{},({Vue:t})=>{t.mixin({computed:{$dataBlock(){return this.$options.__data__block__}}})},{},{}],Ls=[];class Rs extends class{constructor(){this.store=new Gn({data:{state:{}}})}$get(t){return this.store.state[t]}$set(t,e){Gn.set(this.store.state,t,e)}$emit(...t){this.store.$emit(...t)}$on(...t){this.store.$on(...t)}}{}Object.assign(Rs.prototype,{getPageAsyncComponent:ss,getLayoutAsyncComponent:cs,getAsyncComponent:us,getVueComponent:ls});var Is={install(t){const e=new Rs;t.$vuepress=e,t.prototype.$vuepress=e}};function Ms(t,e){const n=e.toLowerCase();return t.options.routes.some(t=>t.path.toLowerCase()===n)}var Ds={props:{pageKey:String,slotKey:{type:String,default:"default"}},render(t){const e=this.pageKey||this.$parent.$page.key;return ps("pageKey",e),Gn.component(e)||Gn.component(e,ss(e)),Gn.component(e)?t(e):t("")}},Ns={functional:!0,props:{slotKey:String,required:!0},render:(t,{props:e,slots:n})=>t("div",{class:["content__"+e.slotKey]},n()[e.slotKey])},Fs={computed:{openInNewWindowTitle(){return this.$themeLocaleConfig.openNewWindowText||"(opens new window)"}}},Us=(n(237),n(238),Object(js.a)(Fs,(function(){var t=this._self._c;return t("span",[t("svg",{staticClass:"icon outbound",attrs:{xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",x:"0px",y:"0px",viewBox:"0 0 100 100",width:"15",height:"15"}},[t("path",{attrs:{fill:"currentColor",d:"M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"}}),this._v(" "),t("polygon",{attrs:{fill:"currentColor",points:"45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"}})]),this._v(" "),t("span",{staticClass:"sr-only"},[this._v(this._s(this.openInNewWindowTitle))])])}),[],!1,null,null,null).exports),zs={functional:!0,render(t,{parent:e,children:n}){if(e._isMounted)return n;e.$once("hook:mounted",()=>{e.$forceUpdate()})}};Gn.config.productionTip=!1,Gn.use(Ha),Gn.use(Is),Gn.mixin(function(t,e,n=Gn){!function(t){t.locales&&Object.keys(t.locales).forEach(e=>{t.locales[e].path=e});Object.freeze(t)}(e),n.$vuepress.$set("siteData",e);const r=new(t(n.$vuepress.$get("siteData"))),o=Object.getOwnPropertyDescriptors(Object.getPrototypeOf(r)),i={};return Object.keys(o).reduce((t,e)=>(e.startsWith("$")&&(t[e]=o[e].get),t),i),{computed:i}}(t=>class{setPage(t){this.__page=t}get $site(){return t}get $themeConfig(){return this.$site.themeConfig}get $frontmatter(){return this.$page.frontmatter}get $localeConfig(){const{locales:t={}}=this.$site;let e,n;for(const r in t)"/"===r?n=t[r]:0===this.$page.path.indexOf(r)&&(e=t[r]);return e||n||{}}get $siteTitle(){return this.$localeConfig.title||this.$site.title||""}get $canonicalUrl(){const{canonicalUrl:t}=this.$page.frontmatter;return"string"==typeof t&&t}get $title(){const t=this.$page,{metaTitle:e}=this.$page.frontmatter;if("string"==typeof e)return e;const n=this.$siteTitle,r=t.frontmatter.home?null:t.frontmatter.title||t.title;return n?r?r+" | "+n:n:r||"VuePress"}get $description(){const t=function(t){if(t){const e=t.filter(t=>"description"===t.name)[0];if(e)return e.content}}(this.$page.frontmatter.meta);return t||(this.$page.frontmatter.description||this.$localeConfig.description||this.$site.description||"")}get $lang(){return this.$page.frontmatter.lang||this.$localeConfig.lang||"en-US"}get $localePath(){return this.$localeConfig.path||"/"}get $themeLocaleConfig(){return(this.$site.themeConfig.locales||{})[this.$localePath]||{}}get $page(){return this.__page?this.__page:function(t,e){for(let n=0;nn||(t.hash?!Gn.$vuepress.$get("disableScrollBehavior")&&{selector:decodeURIComponent(t.hash)}:{x:0,y:0})});!function(t){t.beforeEach((e,n,r)=>{if(Ms(t,e.path))r();else if(/(\/|\.html)$/.test(e.path))if(/\/$/.test(e.path)){const n=e.path.replace(/\/$/,"")+".html";Ms(t,n)?r(n):r()}else r();else{const n=e.path+"/",o=e.path+".html";Ms(t,o)?r(o):Ms(t,n)?r(n):r()}})}(n);const r={};try{await Promise.all(Ts.filter(t=>"function"==typeof t).map(e=>e({Vue:Gn,options:r,router:n,siteData:As,isServer:t})))}catch(t){console.error(t)}return{app:new Gn(Object.assign(r,{router:n,render:t=>t("div",{attrs:{id:"app"}},[t("RouterView",{ref:"layout"}),t("div",{class:"global-ui"},Ls.map(e=>t(e)))])})),router:n}}(!1).then(({app:t,router:e})=>{e.onReady(()=>{t.$mount("#app")})})}]); \ No newline at end of file +var r=Object.freeze({}),o=Array.isArray;function i(t){return null==t}function a(t){return null!=t}function s(t){return!0===t}function c(t){return"string"==typeof t||"number"==typeof t||"symbol"==typeof t||"boolean"==typeof t}function u(t){return"function"==typeof t}function l(t){return null!==t&&"object"==typeof t}var f=Object.prototype.toString;function p(t){return"[object Object]"===f.call(t)}function d(t){return"[object RegExp]"===f.call(t)}function h(t){var e=parseFloat(String(t));return e>=0&&Math.floor(e)===e&&isFinite(t)}function v(t){return a(t)&&"function"==typeof t.then&&"function"==typeof t.catch}function m(t){return null==t?"":Array.isArray(t)||p(t)&&t.toString===f?JSON.stringify(t,y,2):String(t)}function y(t,e){return e&&e.__v_isRef?e.value:e}function g(t){var e=parseFloat(t);return isNaN(e)?t:e}function b(t,e){for(var n=Object.create(null),r=t.split(","),o=0;o-1)return t.splice(r,1)}}var w=Object.prototype.hasOwnProperty;function O(t,e){return w.call(t,e)}function C(t){var e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}var $=/-(\w)/g,k=C((function(t){return t.replace($,(function(t,e){return e?e.toUpperCase():""}))})),S=C((function(t){return t.charAt(0).toUpperCase()+t.slice(1)})),j=/\B([A-Z])/g,E=C((function(t){return t.replace(j,"-$1").toLowerCase()}));var P=Function.prototype.bind?function(t,e){return t.bind(e)}:function(t,e){function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}return n._length=t.length,n};function A(t,e){e=e||0;for(var n=t.length-e,r=new Array(n);n--;)r[n]=t[n+e];return r}function T(t,e){for(var n in e)t[n]=e[n];return t}function L(t){for(var e={},n=0;n0,Y=J&&J.indexOf("edge/")>0;J&&J.indexOf("android");var tt=J&&/iphone|ipad|ipod|ios/.test(J);J&&/chrome\/\d+/.test(J),J&&/phantomjs/.test(J);var et,nt=J&&J.match(/firefox\/(\d+)/),rt={}.watch,ot=!1;if(Q)try{var it={};Object.defineProperty(it,"passive",{get:function(){ot=!0}}),window.addEventListener("test-passive",null,it)}catch(t){}var at=function(){return void 0===et&&(et=!Q&&"undefined"!=typeof global&&(global.process&&"server"===global.process.env.VUE_ENV)),et},st=Q&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function ct(t){return"function"==typeof t&&/native code/.test(t.toString())}var ut,lt="undefined"!=typeof Symbol&&ct(Symbol)&&"undefined"!=typeof Reflect&&ct(Reflect.ownKeys);ut="undefined"!=typeof Set&&ct(Set)?Set:function(){function t(){this.set=Object.create(null)}return t.prototype.has=function(t){return!0===this.set[t]},t.prototype.add=function(t){this.set[t]=!0},t.prototype.clear=function(){this.set=Object.create(null)},t}();var ft=null;function pt(t){void 0===t&&(t=null),t||ft&&ft._scope.off(),ft=t,t&&t._scope.on()}var dt=function(){function t(t,e,n,r,o,i,a,s){this.tag=t,this.data=e,this.children=n,this.text=r,this.elm=o,this.ns=void 0,this.context=i,this.fnContext=void 0,this.fnOptions=void 0,this.fnScopeId=void 0,this.key=e&&e.key,this.componentOptions=a,this.componentInstance=void 0,this.parent=void 0,this.raw=!1,this.isStatic=!1,this.isRootInsert=!0,this.isComment=!1,this.isCloned=!1,this.isOnce=!1,this.asyncFactory=s,this.asyncMeta=void 0,this.isAsyncPlaceholder=!1}return Object.defineProperty(t.prototype,"child",{get:function(){return this.componentInstance},enumerable:!1,configurable:!0}),t}(),ht=function(t){void 0===t&&(t="");var e=new dt;return e.text=t,e.isComment=!0,e};function vt(t){return new dt(void 0,void 0,void 0,String(t))}function mt(t){var e=new dt(t.tag,t.data,t.children&&t.children.slice(),t.text,t.elm,t.context,t.componentOptions,t.asyncFactory);return e.ns=t.ns,e.isStatic=t.isStatic,e.key=t.key,e.isComment=t.isComment,e.fnContext=t.fnContext,e.fnOptions=t.fnOptions,e.fnScopeId=t.fnScopeId,e.asyncMeta=t.asyncMeta,e.isCloned=!0,e}"function"==typeof SuppressedError&&SuppressedError;var yt=0,gt=[],bt=function(){function t(){this._pending=!1,this.id=yt++,this.subs=[]}return t.prototype.addSub=function(t){this.subs.push(t)},t.prototype.removeSub=function(t){this.subs[this.subs.indexOf(t)]=null,this._pending||(this._pending=!0,gt.push(this))},t.prototype.depend=function(e){t.target&&t.target.addDep(this)},t.prototype.notify=function(t){var e=this.subs.filter((function(t){return t}));for(var n=0,r=e.length;n0&&(Jt((u=t(u,"".concat(n||"","_").concat(r)))[0])&&Jt(f)&&(p[l]=vt(f.text+u[0].text),u.shift()),p.push.apply(p,u)):c(u)?Jt(f)?p[l]=vt(f.text+u):""!==u&&p.push(vt(u)):Jt(u)&&Jt(f)?p[l]=vt(f.text+u.text):(s(e._isVList)&&a(u.tag)&&i(u.key)&&a(n)&&(u.key="__vlist".concat(n,"_").concat(r,"__")),p.push(u)));return p}(t):void 0}function Jt(t){return a(t)&&a(t.text)&&!1===t.isComment}function Zt(t,e){var n,r,i,s,c=null;if(o(t)||"string"==typeof t)for(c=new Array(t.length),n=0,r=t.length;n0,s=e?!!e.$stable:!a,c=e&&e.$key;if(e){if(e._normalized)return e._normalized;if(s&&o&&o!==r&&c===o.$key&&!a&&!o.$hasNormal)return o;for(var u in i={},e)e[u]&&"$"!==u[0]&&(i[u]=me(t,n,u,e[u]))}else i={};for(var l in n)l in i||(i[l]=ye(n,l));return e&&Object.isExtensible(e)&&(e._normalized=i),W(i,"$stable",s),W(i,"$key",c),W(i,"$hasNormal",a),i}function me(t,e,n,r){var i=function(){var e=ft;pt(t);var n=arguments.length?r.apply(null,arguments):r({}),i=(n=n&&"object"==typeof n&&!o(n)?[n]:Qt(n))&&n[0];return pt(e),n&&(!i||1===n.length&&i.isComment&&!he(i))?void 0:n};return r.proxy&&Object.defineProperty(e,n,{get:i,enumerable:!0,configurable:!0}),i}function ye(t,e){return function(){return t[e]}}function ge(t){return{get attrs(){if(!t._attrsProxy){var e=t._attrsProxy={};W(e,"_v_attr_proxy",!0),be(e,t.$attrs,r,t,"$attrs")}return t._attrsProxy},get listeners(){t._listenersProxy||be(t._listenersProxy={},t.$listeners,r,t,"$listeners");return t._listenersProxy},get slots(){return function(t){t._slotsProxy||xe(t._slotsProxy={},t.$scopedSlots);return t._slotsProxy}(t)},emit:P(t.$emit,t),expose:function(e){e&&Object.keys(e).forEach((function(n){return Ut(t,e,n)}))}}}function be(t,e,n,r,o){var i=!1;for(var a in e)a in t?e[a]!==n[a]&&(i=!0):(i=!0,_e(t,a,r,o));for(var a in t)a in e||(i=!0,delete t[a]);return i}function _e(t,e,n,r){Object.defineProperty(t,e,{enumerable:!0,configurable:!0,get:function(){return n[r][e]}})}function xe(t,e){for(var n in e)t[n]=e[n];for(var n in t)n in e||delete t[n]}var we=null;function Oe(t,e){return(t.__esModule||lt&&"Module"===t[Symbol.toStringTag])&&(t=t.default),l(t)?e.extend(t):t}function Ce(t){if(o(t))for(var e=0;edocument.createEvent("Event").timeStamp&&(un=function(){return ln.now()})}var fn=function(t,e){if(t.post){if(!e.post)return 1}else if(e.post)return-1;return t.id-e.id};function pn(){var t,e;for(cn=un(),an=!0,en.sort(fn),sn=0;snsn&&en[n].id>t.id;)n--;en.splice(n+1,0,t)}else en.push(t);on||(on=!0,Fe(pn))}}function hn(t,e){if(t){for(var n=Object.create(null),r=lt?Reflect.ownKeys(t):Object.keys(t),o=0;o-1)if(i&&!O(o,"default"))a=!1;else if(""===a||a===E(t)){var c=Mn(String,o.type);(c<0||s-1:"string"==typeof t?t.split(",").indexOf(e)>-1:!!d(t)&&t.test(e)}function Zn(t,e){var n=t.cache,r=t.keys,o=t._vnode,i=t.$vnode;for(var a in n){var s=n[a];if(s){var c=s.name;c&&!e(c)&&Xn(n,a,r,o)}}i.componentOptions.children=void 0}function Xn(t,e,n,r){var o=t[e];!o||r&&o.tag===r.tag||o.componentInstance.$destroy(),t[e]=null,x(n,e)}Gn.prototype._init=function(t){var e=this;e._uid=Hn++,e._isVue=!0,e.__v_skip=!0,e._scope=new Bt(!0),e._scope.parent=void 0,e._scope._vm=!0,t&&t._isComponent?function(t,e){var n=t.$options=Object.create(t.constructor.options),r=e._parentVnode;n.parent=e.parent,n._parentVnode=r;var o=r.componentOptions;n.propsData=o.propsData,n._parentListeners=o.listeners,n._renderChildren=o.children,n._componentTag=o.tag,e.render&&(n.render=e.render,n.staticRenderFns=e.staticRenderFns)}(e,t):e.$options=Pn(Wn(e.constructor),t||{},e),e._renderProxy=e,e._self=e,function(t){var e=t.$options,n=e.parent;if(n&&!e.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(t)}t.$parent=n,t.$root=n?n.$root:t,t.$children=[],t.$refs={},t._provided=n?n._provided:Object.create(null),t._watcher=null,t._inactive=null,t._directInactive=!1,t._isMounted=!1,t._isDestroyed=!1,t._isBeingDestroyed=!1}(e),function(t){t._events=Object.create(null),t._hasHookEvent=!1;var e=t.$options._parentListeners;e&&Qe(t,e)}(e),function(t){t._vnode=null,t._staticTrees=null;var e=t.$options,n=t.$vnode=e._parentVnode,o=n&&n.context;t.$slots=pe(e._renderChildren,o),t.$scopedSlots=n?ve(t.$parent,n.data.scopedSlots,t.$slots):r,t._c=function(e,n,r,o){return $e(t,e,n,r,o,!1)},t.$createElement=function(e,n,r,o){return $e(t,e,n,r,o,!0)};var i=n&&n.data;Tt(t,"$attrs",i&&i.attrs||r,null,!0),Tt(t,"$listeners",e._parentListeners||r,null,!0)}(e),tn(e,"beforeCreate",void 0,!1),function(t){var e=hn(t.$options.inject,t);e&&(jt(!1),Object.keys(e).forEach((function(n){Tt(t,n,e[n])})),jt(!0))}(e),Fn(e),function(t){var e=t.$options.provide;if(e){var n=u(e)?e.call(t):e;if(!l(n))return;for(var r=qt(t),o=lt?Reflect.ownKeys(n):Object.keys(n),i=0;i1?A(n):n;for(var r=A(arguments,1),o='event handler for "'.concat(t,'"'),i=0,a=n.length;iparseInt(this.max)&&Xn(t,e[0],e,this._vnode),this.vnodeToCache=null}}},created:function(){this.cache=Object.create(null),this.keys=[]},destroyed:function(){for(var t in this.cache)Xn(this.cache,t,this.keys)},mounted:function(){var t=this;this.cacheVNode(),this.$watch("include",(function(e){Zn(t,(function(t){return Jn(e,t)}))})),this.$watch("exclude",(function(e){Zn(t,(function(t){return!Jn(e,t)}))}))},updated:function(){this.cacheVNode()},render:function(){var t=this.$slots.default,e=Ce(t),n=e&&e.componentOptions;if(n){var r=Qn(n),o=this.include,i=this.exclude;if(o&&(!r||!Jn(o,r))||i&&r&&Jn(i,r))return e;var a=this.cache,s=this.keys,c=null==e.key?n.Ctor.cid+(n.tag?"::".concat(n.tag):""):e.key;a[c]?(e.componentInstance=a[c].componentInstance,x(s,c),s.push(c)):(this.vnodeToCache=e,this.keyToCache=c),e.data.keepAlive=!0}return e||t&&t[0]}}};!function(t){var e={get:function(){return q}};Object.defineProperty(t,"config",e),t.util={warn:On,extend:T,mergeOptions:Pn,defineReactive:Tt},t.set=Lt,t.delete=Rt,t.nextTick=Fe,t.observable=function(t){return At(t),t},t.options=Object.create(null),z.forEach((function(e){t.options[e+"s"]=Object.create(null)})),t.options._base=t,T(t.options.components,tr),function(t){t.use=function(t){var e=this._installedPlugins||(this._installedPlugins=[]);if(e.indexOf(t)>-1)return this;var n=A(arguments,1);return n.unshift(this),u(t.install)?t.install.apply(t,n):u(t)&&t.apply(null,n),e.push(t),this}}(t),function(t){t.mixin=function(t){return this.options=Pn(this.options,t),this}}(t),Kn(t),function(t){z.forEach((function(e){t[e]=function(t,n){return n?("component"===e&&p(n)&&(n.name=n.name||t,n=this.options._base.extend(n)),"directive"===e&&u(n)&&(n={bind:n,update:n}),this.options[e+"s"][t]=n,n):this.options[e+"s"][t]}}))}(t)}(Gn),Object.defineProperty(Gn.prototype,"$isServer",{get:at}),Object.defineProperty(Gn.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(Gn,"FunctionalRenderContext",{value:vn}),Gn.version="2.7.16";var er=b("style,class"),nr=b("input,textarea,option,select,progress"),rr=b("contenteditable,draggable,spellcheck"),or=b("events,caret,typing,plaintext-only"),ir=b("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,truespeed,typemustmatch,visible"),ar="http://www.w3.org/1999/xlink",sr=function(t){return":"===t.charAt(5)&&"xlink"===t.slice(0,5)},cr=function(t){return sr(t)?t.slice(6,t.length):""},ur=function(t){return null==t||!1===t};function lr(t){for(var e=t.data,n=t,r=t;a(r.componentInstance);)(r=r.componentInstance._vnode)&&r.data&&(e=fr(r.data,e));for(;a(n=n.parent);)n&&n.data&&(e=fr(e,n.data));return function(t,e){if(a(t)||a(e))return pr(t,dr(e));return""}(e.staticClass,e.class)}function fr(t,e){return{staticClass:pr(t.staticClass,e.staticClass),class:a(t.class)?[t.class,e.class]:e.class}}function pr(t,e){return t?e?t+" "+e:t:e||""}function dr(t){return Array.isArray(t)?function(t){for(var e,n="",r=0,o=t.length;r-1?Dr(t,e,n):ir(e)?ur(n)?t.removeAttribute(e):(n="allowfullscreen"===e&&"EMBED"===t.tagName?"true":e,t.setAttribute(e,n)):rr(e)?t.setAttribute(e,function(t,e){return ur(e)||"false"===e?"false":"contenteditable"===t&&or(e)?e:"true"}(e,n)):sr(e)?ur(n)?t.removeAttributeNS(ar,cr(e)):t.setAttributeNS(ar,e,n):Dr(t,e,n)}function Dr(t,e,n){if(ur(n))t.removeAttribute(e);else{if(Z&&!X&&"TEXTAREA"===t.tagName&&"placeholder"===e&&""!==n&&!t.__ieph){var r=function(e){e.stopImmediatePropagation(),t.removeEventListener("input",r)};t.addEventListener("input",r),t.__ieph=!0}t.setAttribute(e,n)}}var Nr={create:Ir,update:Ir};function Fr(t,e){var n=e.elm,r=e.data,o=t.data;if(!(i(r.staticClass)&&i(r.class)&&(i(o)||i(o.staticClass)&&i(o.class)))){var s=lr(e),c=n._transitionClasses;a(c)&&(s=pr(s,dr(c))),s!==n._prevClass&&(n.setAttribute("class",s),n._prevClass=s)}}var Ur,zr={create:Fr,update:Fr};function Br(t,e,n){var r=Ur;return function o(){var i=e.apply(null,arguments);null!==i&&Hr(t,o,n,r)}}var qr=Ae&&!(nt&&Number(nt[1])<=53);function Vr(t,e,n,r){if(qr){var o=cn,i=e;e=i._wrapper=function(t){if(t.target===t.currentTarget||t.timeStamp>=o||t.timeStamp<=0||t.target.ownerDocument!==document)return i.apply(this,arguments)}}Ur.addEventListener(t,e,ot?{capture:n,passive:r}:n)}function Hr(t,e,n,r){(r||Ur).removeEventListener(t,e._wrapper||e,n)}function Wr(t,e){if(!i(t.data.on)||!i(e.data.on)){var n=e.data.on||{},r=t.data.on||{};Ur=e.elm||t.elm,function(t){if(a(t.__r)){var e=Z?"change":"input";t[e]=[].concat(t.__r,t[e]||[]),delete t.__r}a(t.__c)&&(t.change=[].concat(t.__c,t.change||[]),delete t.__c)}(n),Wt(n,r,Vr,Hr,Br,e.context),Ur=void 0}}var Gr,Kr={create:Wr,update:Wr,destroy:function(t){return Wr(t,Cr)}};function Qr(t,e){if(!i(t.data.domProps)||!i(e.data.domProps)){var n,r,o=e.elm,c=t.data.domProps||{},u=e.data.domProps||{};for(n in(a(u.__ob__)||s(u._v_attr_proxy))&&(u=e.data.domProps=T({},u)),c)n in u||(o[n]="");for(n in u){if(r=u[n],"textContent"===n||"innerHTML"===n){if(e.children&&(e.children.length=0),r===c[n])continue;1===o.childNodes.length&&o.removeChild(o.childNodes[0])}if("value"===n&&"PROGRESS"!==o.tagName){o._value=r;var l=i(r)?"":String(r);Jr(o,l)&&(o.value=l)}else if("innerHTML"===n&&mr(o.tagName)&&i(o.innerHTML)){(Gr=Gr||document.createElement("div")).innerHTML="".concat(r,"");for(var f=Gr.firstChild;o.firstChild;)o.removeChild(o.firstChild);for(;f.firstChild;)o.appendChild(f.firstChild)}else if(r!==c[n])try{o[n]=r}catch(t){}}}}function Jr(t,e){return!t.composing&&("OPTION"===t.tagName||function(t,e){var n=!0;try{n=document.activeElement!==t}catch(t){}return n&&t.value!==e}(t,e)||function(t,e){var n=t.value,r=t._vModifiers;if(a(r)){if(r.number)return g(n)!==g(e);if(r.trim)return n.trim()!==e.trim()}return n!==e}(t,e))}var Zr={create:Qr,update:Qr},Xr=C((function(t){var e={},n=/:(.+)/;return t.split(/;(?![^(]*\))/g).forEach((function(t){if(t){var r=t.split(n);r.length>1&&(e[r[0].trim()]=r[1].trim())}})),e}));function Yr(t){var e=to(t.style);return t.staticStyle?T(t.staticStyle,e):e}function to(t){return Array.isArray(t)?L(t):"string"==typeof t?Xr(t):t}var eo,no=/^--/,ro=/\s*!important$/,oo=function(t,e,n){if(no.test(e))t.style.setProperty(e,n);else if(ro.test(n))t.style.setProperty(E(e),n.replace(ro,""),"important");else{var r=ao(e);if(Array.isArray(n))for(var o=0,i=n.length;o-1?e.split(uo).forEach((function(e){return t.classList.add(e)})):t.classList.add(e);else{var n=" ".concat(t.getAttribute("class")||""," ");n.indexOf(" "+e+" ")<0&&t.setAttribute("class",(n+e).trim())}}function fo(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.split(uo).forEach((function(e){return t.classList.remove(e)})):t.classList.remove(e),t.classList.length||t.removeAttribute("class");else{for(var n=" ".concat(t.getAttribute("class")||""," "),r=" "+e+" ";n.indexOf(r)>=0;)n=n.replace(r," ");(n=n.trim())?t.setAttribute("class",n):t.removeAttribute("class")}}function po(t){if(t){if("object"==typeof t){var e={};return!1!==t.css&&T(e,ho(t.name||"v")),T(e,t),e}return"string"==typeof t?ho(t):void 0}}var ho=C((function(t){return{enterClass:"".concat(t,"-enter"),enterToClass:"".concat(t,"-enter-to"),enterActiveClass:"".concat(t,"-enter-active"),leaveClass:"".concat(t,"-leave"),leaveToClass:"".concat(t,"-leave-to"),leaveActiveClass:"".concat(t,"-leave-active")}})),vo=Q&&!X,mo="transition",yo="transitionend",go="animation",bo="animationend";vo&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(mo="WebkitTransition",yo="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(go="WebkitAnimation",bo="webkitAnimationEnd"));var _o=Q?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(t){return t()};function xo(t){_o((function(){_o(t)}))}function wo(t,e){var n=t._transitionClasses||(t._transitionClasses=[]);n.indexOf(e)<0&&(n.push(e),lo(t,e))}function Oo(t,e){t._transitionClasses&&x(t._transitionClasses,e),fo(t,e)}function Co(t,e,n){var r=ko(t,e),o=r.type,i=r.timeout,a=r.propCount;if(!o)return n();var s="transition"===o?yo:bo,c=0,u=function(){t.removeEventListener(s,l),n()},l=function(e){e.target===t&&++c>=a&&u()};setTimeout((function(){c0&&(n="transition",l=a,f=i.length):"animation"===e?u>0&&(n="animation",l=u,f=c.length):f=(n=(l=Math.max(a,u))>0?a>u?"transition":"animation":null)?"transition"===n?i.length:c.length:0,{type:n,timeout:l,propCount:f,hasTransform:"transition"===n&&$o.test(r[mo+"Property"])}}function So(t,e){for(;t.length1}function Lo(t,e){!0!==e.data.show&&Eo(e)}var Ro=function(t){var e,n,r={},u=t.modules,l=t.nodeOps;for(e=0;e<$r.length;++e)for(r[$r[e]]=[],n=0;nh?_(t,i(n[y+1])?null:n[y+1].elm,n,d,y,r):d>y&&w(e,f,h)}(f,v,y,n,u):a(y)?(a(t.text)&&l.setTextContent(f,""),_(f,null,y,0,y.length-1,n)):a(v)?w(v,0,v.length-1):a(t.text)&&l.setTextContent(f,""):t.text!==e.text&&l.setTextContent(f,e.text),a(h)&&a(d=h.hook)&&a(d=d.postpatch)&&d(t,e)}}}function k(t,e,n){if(s(n)&&a(t.parent))t.parent.data.pendingInsert=e;else for(var r=0;r-1,a.selected!==i&&(a.selected=i);else if(D(Fo(a),r))return void(t.selectedIndex!==s&&(t.selectedIndex=s));o||(t.selectedIndex=-1)}}function No(t,e){return e.every((function(e){return!D(e,t)}))}function Fo(t){return"_value"in t?t._value:t.value}function Uo(t){t.target.composing=!0}function zo(t){t.target.composing&&(t.target.composing=!1,Bo(t.target,"input"))}function Bo(t,e){var n=document.createEvent("HTMLEvents");n.initEvent(e,!0,!0),t.dispatchEvent(n)}function qo(t){return!t.componentInstance||t.data&&t.data.transition?t:qo(t.componentInstance._vnode)}var Vo={model:Io,show:{bind:function(t,e,n){var r=e.value,o=(n=qo(n)).data&&n.data.transition,i=t.__vOriginalDisplay="none"===t.style.display?"":t.style.display;r&&o?(n.data.show=!0,Eo(n,(function(){t.style.display=i}))):t.style.display=r?i:"none"},update:function(t,e,n){var r=e.value;!r!=!e.oldValue&&((n=qo(n)).data&&n.data.transition?(n.data.show=!0,r?Eo(n,(function(){t.style.display=t.__vOriginalDisplay})):Po(n,(function(){t.style.display="none"}))):t.style.display=r?t.__vOriginalDisplay:"none")},unbind:function(t,e,n,r,o){o||(t.style.display=t.__vOriginalDisplay)}}},Ho={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]};function Wo(t){var e=t&&t.componentOptions;return e&&e.Ctor.options.abstract?Wo(Ce(e.children)):t}function Go(t){var e={},n=t.$options;for(var r in n.propsData)e[r]=t[r];var o=n._parentListeners;for(var r in o)e[k(r)]=o[r];return e}function Ko(t,e){if(/\d-keep-alive$/.test(e.tag))return t("keep-alive",{props:e.componentOptions.propsData})}var Qo=function(t){return t.tag||he(t)},Jo=function(t){return"show"===t.name},Zo={name:"transition",props:Ho,abstract:!0,render:function(t){var e=this,n=this.$slots.default;if(n&&(n=n.filter(Qo)).length){0;var r=this.mode;0;var o=n[0];if(function(t){for(;t=t.parent;)if(t.data.transition)return!0}(this.$vnode))return o;var i=Wo(o);if(!i)return o;if(this._leaving)return Ko(t,o);var a="__transition-".concat(this._uid,"-");i.key=null==i.key?i.isComment?a+"comment":a+i.tag:c(i.key)?0===String(i.key).indexOf(a)?i.key:a+i.key:i.key;var s=(i.data||(i.data={})).transition=Go(this),u=this._vnode,l=Wo(u);if(i.data.directives&&i.data.directives.some(Jo)&&(i.data.show=!0),l&&l.data&&!function(t,e){return e.key===t.key&&e.tag===t.tag}(i,l)&&!he(l)&&(!l.componentInstance||!l.componentInstance._vnode.isComment)){var f=l.data.transition=T({},s);if("out-in"===r)return this._leaving=!0,Gt(f,"afterLeave",(function(){e._leaving=!1,e.$forceUpdate()})),Ko(t,o);if("in-out"===r){if(he(i))return u;var p,d=function(){p()};Gt(s,"afterEnter",d),Gt(s,"enterCancelled",d),Gt(f,"delayLeave",(function(t){p=t}))}}return o}}},Xo=T({tag:String,moveClass:String},Ho);function Yo(t){t.elm._moveCb&&t.elm._moveCb(),t.elm._enterCb&&t.elm._enterCb()}function ti(t){t.data.newPos=t.elm.getBoundingClientRect()}function ei(t){var e=t.data.pos,n=t.data.newPos,r=e.left-n.left,o=e.top-n.top;if(r||o){t.data.moved=!0;var i=t.elm.style;i.transform=i.WebkitTransform="translate(".concat(r,"px,").concat(o,"px)"),i.transitionDuration="0s"}}delete Xo.mode;var ni={Transition:Zo,TransitionGroup:{props:Xo,beforeMount:function(){var t=this,e=this._update;this._update=function(n,r){var o=Ze(t);t.__patch__(t._vnode,t.kept,!1,!0),t._vnode=t.kept,o(),e.call(t,n,r)}},render:function(t){for(var e=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,o=this.$slots.default||[],i=this.children=[],a=Go(this),s=0;s-1?gr[t]=e.constructor===window.HTMLUnknownElement||e.constructor===window.HTMLElement:gr[t]=/HTMLUnknownElement/.test(e.toString())},T(Gn.options.directives,Vo),T(Gn.options.components,ni),Gn.prototype.__patch__=Q?Ro:R,Gn.prototype.$mount=function(t,e){return function(t,e,n){var r;t.$el=e,t.$options.render||(t.$options.render=ht),tn(t,"beforeMount"),r=function(){t._update(t._render(),n)},new He(t,r,R,{before:function(){t._isMounted&&!t._isDestroyed&&tn(t,"beforeUpdate")}},!0),n=!1;var o=t._preWatchers;if(o)for(var i=0;i=0&&(e=t.slice(r),t=t.slice(0,r));var o=t.indexOf("?");return o>=0&&(n=t.slice(o+1),t=t.slice(0,o)),{path:t,query:n,hash:e}}(o.path||""),u=e&&e.path||"/",l=c.path?Oi(c.path,u,n||o.append):u,f=function(t,e,n){void 0===e&&(e={});var r,o=n||li;try{r=o(t||"")}catch(t){r={}}for(var i in e){var a=e[i];r[i]=Array.isArray(a)?a.map(ui):ui(a)}return r}(c.query,o.query,r&&r.options.parseQuery),p=o.hash||c.hash;return p&&"#"!==p.charAt(0)&&(p="#"+p),{_normalized:!0,path:l,query:f,hash:p}}var Vi,Hi=function(){},Wi={name:"RouterLink",props:{to:{type:[String,Object],required:!0},tag:{type:String,default:"a"},custom:Boolean,exact:Boolean,exactPath:Boolean,append:Boolean,replace:Boolean,activeClass:String,exactActiveClass:String,ariaCurrentValue:{type:String,default:"page"},event:{type:[String,Array],default:"click"}},render:function(t){var e=this,n=this.$router,r=this.$route,o=n.resolve(this.to,r,this.append),i=o.location,a=o.route,s=o.href,c={},u=n.options.linkActiveClass,l=n.options.linkExactActiveClass,f=null==u?"router-link-active":u,p=null==l?"router-link-exact-active":l,d=null==this.activeClass?f:this.activeClass,h=null==this.exactActiveClass?p:this.exactActiveClass,v=a.redirectedFrom?di(null,qi(a.redirectedFrom),null,n):a;c[h]=gi(r,v,this.exactPath),c[d]=this.exact||this.exactPath?c[h]:function(t,e){return 0===t.path.replace(pi,"/").indexOf(e.path.replace(pi,"/"))&&(!e.hash||t.hash===e.hash)&&function(t,e){for(var n in e)if(!(n in t))return!1;return!0}(t.query,e.query)}(r,v);var m=c[h]?this.ariaCurrentValue:null,y=function(t){Gi(t)&&(e.replace?n.replace(i,Hi):n.push(i,Hi))},g={click:Gi};Array.isArray(this.event)?this.event.forEach((function(t){g[t]=y})):g[this.event]=y;var b={class:c},_=!this.$scopedSlots.$hasNormal&&this.$scopedSlots.default&&this.$scopedSlots.default({href:s,route:a,navigate:y,isActive:c[d],isExactActive:c[h]});if(_){if(1===_.length)return _[0];if(_.length>1||!_.length)return 0===_.length?t():t("span",{},_)}if("a"===this.tag)b.on=g,b.attrs={href:s,"aria-current":m};else{var x=function t(e){var n;if(e)for(var r=0;r-1&&(s.params[p]=n.params[p]);return s.path=Bi(l.path,s.params),c(l,s,a)}if(s.path){s.params={};for(var d=0;d-1}function Ca(t,e){return Oa(t)&&t._isRouter&&(null==e||t.type===e)}function $a(t,e,n){var r=function(o){o>=t.length?n():t[o]?e(t[o],(function(){r(o+1)})):r(o+1)};r(0)}function ka(t){return function(e,n,r){var o=!1,i=0,a=null;Sa(t,(function(t,e,n,s){if("function"==typeof t&&void 0===t.cid){o=!0,i++;var c,u=Pa((function(e){var o;((o=e).__esModule||Ea&&"Module"===o[Symbol.toStringTag])&&(e=e.default),t.resolved="function"==typeof e?e:Vi.extend(e),n.components[s]=e,--i<=0&&r()})),l=Pa((function(t){var e="Failed to resolve async component "+s+": "+t;a||(a=Oa(t)?t:new Error(e),r(a))}));try{c=t(u,l)}catch(t){l(t)}if(c)if("function"==typeof c.then)c.then(u,l);else{var f=c.component;f&&"function"==typeof f.then&&f.then(u,l)}}})),o||r()}}function Sa(t,e){return ja(t.map((function(t){return Object.keys(t.components).map((function(n){return e(t.components[n],t.instances[n],t,n)}))})))}function ja(t){return Array.prototype.concat.apply([],t)}var Ea="function"==typeof Symbol&&"symbol"==typeof Symbol.toStringTag;function Pa(t){var e=!1;return function(){for(var n=[],r=arguments.length;r--;)n[r]=arguments[r];if(!e)return e=!0,t.apply(this,n)}}var Aa=function(t,e){this.router=t,this.base=function(t){if(!t)if(Ki){var e=document.querySelector("base");t=(t=e&&e.getAttribute("href")||"/").replace(/^https?:\/\/[^\/]+/,"")}else t="/";"/"!==t.charAt(0)&&(t="/"+t);return t.replace(/\/$/,"")}(e),this.current=vi,this.pending=null,this.ready=!1,this.readyCbs=[],this.readyErrorCbs=[],this.errorCbs=[],this.listeners=[]};function Ta(t,e,n,r){var o=Sa(t,(function(t,r,o,i){var a=function(t,e){"function"!=typeof t&&(t=Vi.extend(t));return t.options[e]}(t,e);if(a)return Array.isArray(a)?a.map((function(t){return n(t,r,o,i)})):n(a,r,o,i)}));return ja(r?o.reverse():o)}function La(t,e){if(e)return function(){return t.apply(e,arguments)}}Aa.prototype.listen=function(t){this.cb=t},Aa.prototype.onReady=function(t,e){this.ready?t():(this.readyCbs.push(t),e&&this.readyErrorCbs.push(e))},Aa.prototype.onError=function(t){this.errorCbs.push(t)},Aa.prototype.transitionTo=function(t,e,n){var r,o=this;try{r=this.router.match(t,this.current)}catch(t){throw this.errorCbs.forEach((function(e){e(t)})),t}var i=this.current;this.confirmTransition(r,(function(){o.updateRoute(r),e&&e(r),o.ensureURL(),o.router.afterHooks.forEach((function(t){t&&t(r,i)})),o.ready||(o.ready=!0,o.readyCbs.forEach((function(t){t(r)})))}),(function(t){n&&n(t),t&&!o.ready&&(Ca(t,ga.redirected)&&i===vi||(o.ready=!0,o.readyErrorCbs.forEach((function(e){e(t)}))))}))},Aa.prototype.confirmTransition=function(t,e,n){var r=this,o=this.current;this.pending=t;var i,a,s=function(t){!Ca(t)&&Oa(t)&&(r.errorCbs.length?r.errorCbs.forEach((function(e){e(t)})):console.error(t)),n&&n(t)},c=t.matched.length-1,u=o.matched.length-1;if(gi(t,o)&&c===u&&t.matched[c]===o.matched[u])return this.ensureURL(),t.hash&&aa(this.router,o,t,!1),s(((a=xa(i=o,t,ga.duplicated,'Avoided redundant navigation to current location: "'+i.fullPath+'".')).name="NavigationDuplicated",a));var l=function(t,e){var n,r=Math.max(t.length,e.length);for(n=0;n0)){var e=this.router,n=e.options.scrollBehavior,r=va&&n;r&&this.listeners.push(ia());var o=function(){var n=t.current,o=Ia(t.base);t.current===vi&&o===t._startLocation||t.transitionTo(o,(function(t){r&&aa(e,t,n,!0)}))};window.addEventListener("popstate",o),this.listeners.push((function(){window.removeEventListener("popstate",o)}))}},e.prototype.go=function(t){window.history.go(t)},e.prototype.push=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){ma(Ci(r.base+t.fullPath)),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){ya(Ci(r.base+t.fullPath)),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.ensureURL=function(t){if(Ia(this.base)!==this.current.fullPath){var e=Ci(this.base+this.current.fullPath);t?ma(e):ya(e)}},e.prototype.getCurrentLocation=function(){return Ia(this.base)},e}(Aa);function Ia(t){var e=window.location.pathname,n=e.toLowerCase(),r=t.toLowerCase();return!t||n!==r&&0!==n.indexOf(Ci(r+"/"))||(e=e.slice(t.length)),(e||"/")+window.location.search+window.location.hash}var Ma=function(t){function e(e,n,r){t.call(this,e,n),r&&function(t){var e=Ia(t);if(!/^\/#/.test(e))return window.location.replace(Ci(t+"/#"+e)),!0}(this.base)||Da()}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.setupListeners=function(){var t=this;if(!(this.listeners.length>0)){var e=this.router.options.scrollBehavior,n=va&&e;n&&this.listeners.push(ia());var r=function(){var e=t.current;Da()&&t.transitionTo(Na(),(function(r){n&&aa(t.router,r,e,!0),va||za(r.fullPath)}))},o=va?"popstate":"hashchange";window.addEventListener(o,r),this.listeners.push((function(){window.removeEventListener(o,r)}))}},e.prototype.push=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){Ua(t.fullPath),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){za(t.fullPath),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.go=function(t){window.history.go(t)},e.prototype.ensureURL=function(t){var e=this.current.fullPath;Na()!==e&&(t?Ua(e):za(e))},e.prototype.getCurrentLocation=function(){return Na()},e}(Aa);function Da(){var t=Na();return"/"===t.charAt(0)||(za("/"+t),!1)}function Na(){var t=window.location.href,e=t.indexOf("#");return e<0?"":t=t.slice(e+1)}function Fa(t){var e=window.location.href,n=e.indexOf("#");return(n>=0?e.slice(0,n):e)+"#"+t}function Ua(t){va?ma(Fa(t)):window.location.hash=t}function za(t){va?ya(Fa(t)):window.location.replace(Fa(t))}var Ba=function(t){function e(e,n){t.call(this,e,n),this.stack=[],this.index=-1}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.push=function(t,e,n){var r=this;this.transitionTo(t,(function(t){r.stack=r.stack.slice(0,r.index+1).concat(t),r.index++,e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var r=this;this.transitionTo(t,(function(t){r.stack=r.stack.slice(0,r.index).concat(t),e&&e(t)}),n)},e.prototype.go=function(t){var e=this,n=this.index+t;if(!(n<0||n>=this.stack.length)){var r=this.stack[n];this.confirmTransition(r,(function(){var t=e.current;e.index=n,e.updateRoute(r),e.router.afterHooks.forEach((function(e){e&&e(r,t)}))}),(function(t){Ca(t,ga.duplicated)&&(e.index=n)}))}},e.prototype.getCurrentLocation=function(){var t=this.stack[this.stack.length-1];return t?t.fullPath:"/"},e.prototype.ensureURL=function(){},e}(Aa),qa=function(t){void 0===t&&(t={}),this.app=null,this.apps=[],this.options=t,this.beforeHooks=[],this.resolveHooks=[],this.afterHooks=[],this.matcher=Zi(t.routes||[],this);var e=t.mode||"hash";switch(this.fallback="history"===e&&!va&&!1!==t.fallback,this.fallback&&(e="hash"),Ki||(e="abstract"),this.mode=e,e){case"history":this.history=new Ra(this,t.base);break;case"hash":this.history=new Ma(this,t.base,this.fallback);break;case"abstract":this.history=new Ba(this,t.base);break;default:0}},Va={currentRoute:{configurable:!0}};qa.prototype.match=function(t,e,n){return this.matcher.match(t,e,n)},Va.currentRoute.get=function(){return this.history&&this.history.current},qa.prototype.init=function(t){var e=this;if(this.apps.push(t),t.$once("hook:destroyed",(function(){var n=e.apps.indexOf(t);n>-1&&e.apps.splice(n,1),e.app===t&&(e.app=e.apps[0]||null),e.app||e.history.teardown()})),!this.app){this.app=t;var n=this.history;if(n instanceof Ra||n instanceof Ma){var r=function(t){n.setupListeners(),function(t){var r=n.current,o=e.options.scrollBehavior;va&&o&&"fullPath"in t&&aa(e,t,r,!1)}(t)};n.transitionTo(n.getCurrentLocation(),r,r)}n.listen((function(t){e.apps.forEach((function(e){e._route=t}))}))}},qa.prototype.beforeEach=function(t){return Wa(this.beforeHooks,t)},qa.prototype.beforeResolve=function(t){return Wa(this.resolveHooks,t)},qa.prototype.afterEach=function(t){return Wa(this.afterHooks,t)},qa.prototype.onReady=function(t,e){this.history.onReady(t,e)},qa.prototype.onError=function(t){this.history.onError(t)},qa.prototype.push=function(t,e,n){var r=this;if(!e&&!n&&"undefined"!=typeof Promise)return new Promise((function(e,n){r.history.push(t,e,n)}));this.history.push(t,e,n)},qa.prototype.replace=function(t,e,n){var r=this;if(!e&&!n&&"undefined"!=typeof Promise)return new Promise((function(e,n){r.history.replace(t,e,n)}));this.history.replace(t,e,n)},qa.prototype.go=function(t){this.history.go(t)},qa.prototype.back=function(){this.go(-1)},qa.prototype.forward=function(){this.go(1)},qa.prototype.getMatchedComponents=function(t){var e=t?t.matched?t:this.resolve(t).route:this.currentRoute;return e?[].concat.apply([],e.matched.map((function(t){return Object.keys(t.components).map((function(e){return t.components[e]}))}))):[]},qa.prototype.resolve=function(t,e,n){var r=qi(t,e=e||this.history.current,n,this),o=this.match(r,e),i=o.redirectedFrom||o.fullPath;return{location:r,route:o,href:function(t,e,n){var r="hash"===n?"#"+e:e;return t?Ci(t+"/"+r):r}(this.history.base,i,this.mode),normalizedTo:r,resolved:o}},qa.prototype.getRoutes=function(){return this.matcher.getRoutes()},qa.prototype.addRoute=function(t,e){this.matcher.addRoute(t,e),this.history.current!==vi&&this.history.transitionTo(this.history.getCurrentLocation())},qa.prototype.addRoutes=function(t){this.matcher.addRoutes(t),this.history.current!==vi&&this.history.transitionTo(this.history.getCurrentLocation())},Object.defineProperties(qa.prototype,Va);var Ha=qa;function Wa(t,e){return t.push(e),function(){var n=t.indexOf(e);n>-1&&t.splice(n,1)}}qa.install=function t(e){if(!t.installed||Vi!==e){t.installed=!0,Vi=e;var n=function(t){return void 0!==t},r=function(t,e){var r=t.$options._parentVnode;n(r)&&n(r=r.data)&&n(r=r.registerRouteInstance)&&r(t,e)};e.mixin({beforeCreate:function(){n(this.$options.router)?(this._routerRoot=this,this._router=this.$options.router,this._router.init(this),e.util.defineReactive(this,"_route",this._router.history.current)):this._routerRoot=this.$parent&&this.$parent._routerRoot||this,r(this,this)},destroyed:function(){r(this)}}),Object.defineProperty(e.prototype,"$router",{get:function(){return this._routerRoot._router}}),Object.defineProperty(e.prototype,"$route",{get:function(){return this._routerRoot._route}}),e.component("RouterView",xi),e.component("RouterLink",Wi);var o=e.config.optionMergeStrategies;o.beforeRouteEnter=o.beforeRouteLeave=o.beforeRouteUpdate=o.created}},qa.version="3.6.5",qa.isNavigationFailure=Ca,qa.NavigationFailureType=ga,qa.START_LOCATION=vi,Ki&&window.Vue&&window.Vue.use(qa);n(97);n(124),n(90);var Ga={"components/AlgoliaSearchBox":()=>Promise.all([n.e(0),n.e(13)]).then(n.bind(null,298)),"components/DropdownLink":()=>Promise.all([n.e(0),n.e(14)]).then(n.bind(null,255)),"components/DropdownTransition":()=>Promise.all([n.e(0),n.e(19)]).then(n.bind(null,243)),"components/Home":()=>Promise.all([n.e(0),n.e(16)]).then(n.bind(null,281)),"components/NavLink":()=>n.e(21).then(n.bind(null,242)),"components/NavLinks":()=>Promise.all([n.e(0),n.e(12)]).then(n.bind(null,266)),"components/Navbar":()=>Promise.all([n.e(0),n.e(1)]).then(n.bind(null,295)),"components/Page":()=>Promise.all([n.e(0),n.e(11)]).then(n.bind(null,282)),"components/PageEdit":()=>Promise.all([n.e(0),n.e(17)]).then(n.bind(null,268)),"components/PageNav":()=>Promise.all([n.e(0),n.e(15)]).then(n.bind(null,269)),"components/Sidebar":()=>Promise.all([n.e(0),n.e(10)]).then(n.bind(null,283)),"components/SidebarButton":()=>Promise.all([n.e(0),n.e(20)]).then(n.bind(null,284)),"components/SidebarGroup":()=>Promise.all([n.e(0),n.e(3)]).then(n.bind(null,267)),"components/SidebarLink":()=>Promise.all([n.e(0),n.e(18)]).then(n.bind(null,256)),"components/SidebarLinks":()=>Promise.all([n.e(0),n.e(3)]).then(n.bind(null,254)),"global-components/Badge":()=>Promise.all([n.e(0),n.e(4)]).then(n.bind(null,303)),"global-components/CodeBlock":()=>Promise.all([n.e(0),n.e(5)]).then(n.bind(null,299)),"global-components/CodeGroup":()=>Promise.all([n.e(0),n.e(6)]).then(n.bind(null,300)),"layouts/404":()=>n.e(7).then(n.bind(null,301)),"layouts/Layout":()=>Promise.all([n.e(0),n.e(1),n.e(2)]).then(n.bind(null,302)),NotFound:()=>n.e(7).then(n.bind(null,301)),Layout:()=>Promise.all([n.e(0),n.e(1),n.e(2)]).then(n.bind(null,302))},Ka={"v-3c88bbf2":()=>n.e(22).then(n.bind(null,304)),"v-0decf914":()=>n.e(23).then(n.bind(null,305)),"v-d7e5bcfc":()=>n.e(24).then(n.bind(null,306)),"v-c864372e":()=>n.e(25).then(n.bind(null,307)),"v-102beaee":()=>n.e(26).then(n.bind(null,308)),"v-23f0ba6e":()=>n.e(27).then(n.bind(null,309)),"v-4419f5c9":()=>n.e(28).then(n.bind(null,310)),"v-05e5796e":()=>n.e(29).then(n.bind(null,311)),"v-6d148503":()=>n.e(30).then(n.bind(null,312)),"v-41c3bc69":()=>n.e(31).then(n.bind(null,313)),"v-2bf9c0ae":()=>n.e(32).then(n.bind(null,314)),"v-1c00b5c9":()=>n.e(33).then(n.bind(null,315)),"v-56e4d50b":()=>n.e(34).then(n.bind(null,316)),"v-4f917bd3":()=>n.e(35).then(n.bind(null,317)),"v-6abbdcee":()=>n.e(38).then(n.bind(null,318)),"v-87b4d6ae":()=>n.e(36).then(n.bind(null,319)),"v-ded899ca":()=>n.e(39).then(n.bind(null,320)),"v-7bafdcee":()=>n.e(37).then(n.bind(null,321)),"v-09883f07":()=>n.e(40).then(n.bind(null,322)),"v-40b685e4":()=>n.e(41).then(n.bind(null,323)),"v-a971ed74":()=>n.e(42).then(n.bind(null,324))};function Qa(t){const e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}const Ja=/-(\w)/g,Za=Qa(t=>t.replace(Ja,(t,e)=>e?e.toUpperCase():"")),Xa=/\B([A-Z])/g,Ya=Qa(t=>t.replace(Xa,"-$1").toLowerCase()),ts=Qa(t=>t.charAt(0).toUpperCase()+t.slice(1));function es(t,e){if(!e)return;if(t(e))return t(e);return e.includes("-")?t(ts(Za(e))):t(ts(e))||t(Ya(e))}const ns=Object.assign({},Ga,Ka),rs=t=>ns[t],os=t=>Ka[t],is=t=>Ga[t],as=t=>Gn.component(t);function ss(t){return es(os,t)}function cs(t){return es(is,t)}function us(t){return es(rs,t)}function ls(t){return es(as,t)}function fs(...t){return Promise.all(t.filter(t=>t).map(async t=>{if(!ls(t)&&us(t)){const e=await us(t)();Gn.component(t,e.default)}}))}function ps(t,e){"undefined"!=typeof window&&window.__VUEPRESS__&&(window.__VUEPRESS__[t]=e)}var ds=n(87),hs=n.n(ds),vs=n(88),ms=n.n(vs),ys={created(){if(this.siteMeta=this.$site.headTags.filter(([t])=>"meta"===t).map(([t,e])=>e),this.$ssrContext){const e=this.getMergedMetaTags();this.$ssrContext.title=this.$title,this.$ssrContext.lang=this.$lang,this.$ssrContext.pageMeta=(t=e)?t.map(t=>{let e="{e+=` ${n}="${ms()(t[n])}"`}),e+">"}).join("\n "):"",this.$ssrContext.canonicalLink=bs(this.$canonicalUrl)}var t},mounted(){this.currentMetaTags=[...document.querySelectorAll("meta")],this.updateMeta(),this.updateCanonicalLink()},methods:{updateMeta(){document.title=this.$title,document.documentElement.lang=this.$lang;const t=this.getMergedMetaTags();this.currentMetaTags=_s(t,this.currentMetaTags)},getMergedMetaTags(){const t=this.$page.frontmatter.meta||[];return hs()([{name:"description",content:this.$description}],t,this.siteMeta,xs)},updateCanonicalLink(){gs(),this.$canonicalUrl&&document.head.insertAdjacentHTML("beforeend",bs(this.$canonicalUrl))}},watch:{$page(){this.updateMeta(),this.updateCanonicalLink()}},beforeDestroy(){_s(null,this.currentMetaTags),gs()}};function gs(){const t=document.querySelector("link[rel='canonical']");t&&t.remove()}function bs(t=""){return t?``:""}function _s(t,e){if(e&&[...e].filter(t=>t.parentNode===document.head).forEach(t=>document.head.removeChild(t)),t)return t.map(t=>{const e=document.createElement("meta");return Object.keys(t).forEach(n=>{e.setAttribute(n,t[n])}),document.head.appendChild(e),e})}function xs(t){for(const e of["name","property","itemprop"])if(t.hasOwnProperty(e))return t[e]+e;return JSON.stringify(t)}var ws=n(89),Os={mounted(){window.addEventListener("scroll",this.onScroll)},methods:{onScroll:n.n(ws)()((function(){this.setActiveHash()}),300),setActiveHash(){const t=[].slice.call(document.querySelectorAll(".sidebar-link")),e=[].slice.call(document.querySelectorAll(".header-anchor")).filter(e=>t.some(t=>t.hash===e.hash)),n=Math.max(window.pageYOffset,document.documentElement.scrollTop,document.body.scrollTop),r=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),o=window.innerHeight+n;for(let t=0;t=i.parentElement.offsetTop+10&&(!a||n{this.$nextTick(()=>{this.$vuepress.$set("disableScrollBehavior",!1)})})}}}},beforeDestroy(){window.removeEventListener("scroll",this.onScroll)}},Cs=n(22),$s=n.n(Cs),ks=[ys,Os,{mounted(){$s.a.configure({showSpinner:!1}),this.$router.beforeEach((t,e,n)=>{t.path===e.path||Gn.component(t.name)||$s.a.start(),n()}),this.$router.afterEach(()=>{$s.a.done(),this.isSidebarOpen=!1})}}],Ss={name:"GlobalLayout",computed:{layout(){const t=this.getLayout();return ps("layout",t),Gn.component(t)}},methods:{getLayout(){if(this.$page.path){const t=this.$page.frontmatter.layout;return t&&(this.$vuepress.getLayoutAsyncComponent(t)||this.$vuepress.getVueComponent(t))?t:"Layout"}return"NotFound"}}},js=n(14),Es=Object(js.a)(Ss,(function(){return(0,this._self._c)(this.layout,{tag:"component"})}),[],!1,null,null,null).exports;!function(t,e,n){switch(e){case"components":t[e]||(t[e]={}),Object.assign(t[e],n);break;case"mixins":t[e]||(t[e]=[]),t[e].push(...n);break;default:throw new Error("Unknown option name.")}}(Es,"mixins",ks);const Ps=[{name:"v-3c88bbf2",path:"/",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-3c88bbf2").then(n)}},{path:"/index.html",redirect:"/"},{name:"v-0decf914",path:"/about/",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-0decf914").then(n)}},{path:"/about/index.html",redirect:"/about/"},{name:"v-d7e5bcfc",path:"/docs/",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-d7e5bcfc").then(n)}},{path:"/docs/index.html",redirect:"/docs/"},{name:"v-c864372e",path:"/docs/adapters.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-c864372e").then(n)}},{name:"v-102beaee",path:"/docs/client-codegen.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-102beaee").then(n)}},{name:"v-23f0ba6e",path:"/docs/client.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-23f0ba6e").then(n)}},{name:"v-4419f5c9",path:"/docs/examples.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-4419f5c9").then(n)}},{name:"v-05e5796e",path:"/docs/federation.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-05e5796e").then(n)}},{name:"v-6d148503",path:"/docs/interop.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-6d148503").then(n)}},{name:"v-41c3bc69",path:"/docs/laminext.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-41c3bc69").then(n)}},{name:"v-2bf9c0ae",path:"/docs/middleware.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-2bf9c0ae").then(n)}},{name:"v-1c00b5c9",path:"/docs/optimization.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-1c00b5c9").then(n)}},{name:"v-56e4d50b",path:"/docs/relay-connections.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-56e4d50b").then(n)}},{name:"v-4f917bd3",path:"/docs/schema-comparison.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-4f917bd3").then(n)}},{name:"v-6abbdcee",path:"/docs/server-codegen.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-6abbdcee").then(n)}},{name:"v-87b4d6ae",path:"/docs/schema-reporting.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-87b4d6ae").then(n)}},{name:"v-ded899ca",path:"/docs/stitching.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-ded899ca").then(n)}},{name:"v-7bafdcee",path:"/docs/schema.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-7bafdcee").then(n)}},{name:"v-09883f07",path:"/docs/tools.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-09883f07").then(n)}},{name:"v-40b685e4",path:"/faq/",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-40b685e4").then(n)}},{path:"/faq/index.html",redirect:"/faq/"},{name:"v-a971ed74",path:"/resources/",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-a971ed74").then(n)}},{path:"/resources/index.html",redirect:"/resources/"},{path:"*",component:Es}],As={title:"",description:"",base:"/caliban/",headTags:[["link",{rel:"icon",href:"/caliban/caliban.png"}]],pages:[{title:"Home",frontmatter:{home:!0,heroImage:"/caliban.svg",actionText:"Get Started →",actionLink:"/docs/",features:[{title:"High performance",details:"While all public interfaces are pure and immutable, the library's internals are optimized for speed."},{title:"Minimal boilerplate",details:"No need to manually define schemas for every type in your API. Let the compiler handle the tedious work."},{title:"Excellent interoperability",details:"Out-of-the-box support for major HTTP server libraries, effect types, JSON libraries, and more."}]},regularPath:"/",relativePath:"README.md",key:"v-3c88bbf2",path:"/"},{title:"About",frontmatter:{},regularPath:"/about/",relativePath:"about/README.md",key:"v-0decf914",path:"/about/"},{title:"Getting Started",frontmatter:{},regularPath:"/docs/",relativePath:"docs/README.md",key:"v-d7e5bcfc",path:"/docs/",headers:[{level:2,title:"A simple schema",slug:"a-simple-schema"},{level:2,title:"Serving over HTTP",slug:"serving-over-http"},{level:2,title:"Interop with 3rd-party libraries",slug:"interop-with-3rd-party-libraries"},{level:2,title:"Where to go next?",slug:"where-to-go-next"}]},{title:"Http Adapters",frontmatter:{},regularPath:"/docs/adapters.html",relativePath:"docs/adapters.md",key:"v-c864372e",path:"/docs/adapters.html",headers:[{level:2,title:"Built-in tapir adapters",slug:"built-in-tapir-adapters"},{level:2,title:"Make your own adapter",slug:"make-your-own-adapter"},{level:2,title:"High-performance QuickAdapter",slug:"high-performance-quickadapter"},{level:3,title:"Usage",slug:"usage"},{level:3,title:"Customization",slug:"customization"}]},{title:"Code Generation",frontmatter:{},regularPath:"/docs/client-codegen.html",relativePath:"docs/client-codegen.md",key:"v-102beaee",path:"/docs/client-codegen.html",headers:[{level:2,title:"CalibanPlugin",slug:"calibanplugin"},{level:3,title:"From a schema file",slug:"from-a-schema-file"},{level:3,title:"From a server URL",slug:"from-a-server-url"},{level:3,title:"Generation settings",slug:"generation-settings"},{level:3,title:"Manual generation",slug:"manual-generation"},{level:2,title:"CompileTimeCalibanPlugin",slug:"compiletimecalibanplugin"},{level:3,title:"Server side configuration",slug:"server-side-configuration"},{level:3,title:"Client side configuration",slug:"client-side-configuration"},{level:3,title:"Additional information about CompileTimeCalibanPlugin",slug:"additional-information-about-compiletimecalibanplugin"}]},{title:"Getting Started",frontmatter:{},regularPath:"/docs/client.html",relativePath:"docs/client.md",key:"v-23f0ba6e",path:"/docs/client.html",headers:[{level:2,title:"Dependencies",slug:"dependencies"},{level:2,title:"Code generation",slug:"code-generation"},{level:2,title:"Query building",slug:"query-building"},{level:2,title:"Request execution",slug:"request-execution"}]},{title:"Examples",frontmatter:{},regularPath:"/docs/examples.html",relativePath:"docs/examples.md",key:"v-4419f5c9",path:"/docs/examples.html"},{title:"Federation",frontmatter:{},regularPath:"/docs/federation.html",relativePath:"docs/federation.md",key:"v-05e5796e",path:"/docs/federation.html",headers:[{level:2,title:"Dependencies",slug:"dependencies"},{level:2,title:"Federating",slug:"federating"},{level:2,title:"Tracing",slug:"tracing"},{level:2,title:"Federation V2",slug:"federation-v2"},{level:3,title:"Customizing Federation",slug:"customizing-federation"}]},{title:"Interop with other libraries",frontmatter:{},regularPath:"/docs/interop.html",relativePath:"docs/interop.md",key:"v-6d148503",path:"/docs/interop.html",headers:[{level:2,title:"Cats Effect",slug:"cats-effect"},{level:2,title:"Monix (only with cats-effect 2.x)",slug:"monix-only-with-cats-effect-2-x"},{level:2,title:"Tapir",slug:"tapir"},{level:3,title:"GraphQL restrictions",slug:"graphql-restrictions"}]},{title:"Laminext Integration",frontmatter:{},regularPath:"/docs/laminext.html",relativePath:"docs/laminext.md",key:"v-41c3bc69",path:"/docs/laminext.html"},{title:"Middleware",frontmatter:{},regularPath:"/docs/middleware.html",relativePath:"docs/middleware.md",key:"v-2bf9c0ae",path:"/docs/middleware.html",headers:[{level:2,title:"Wrapper types",slug:"wrapper-types"},{level:2,title:"Pre-defined wrappers",slug:"pre-defined-wrappers"},{level:2,title:"Wrapping the interpreter",slug:"wrapping-the-interpreter"},{level:2,title:"Customizing error responses",slug:"customizing-error-responses"},{level:2,title:"Wrapping the GraphQL",slug:"wrapping-the-graphql"},{level:2,title:"Cost Estimation",slug:"cost-estimation"},{level:2,title:"OpenTelemetry Tracing",slug:"opentelemetry-tracing"}]},{title:"Query optimization",frontmatter:{},regularPath:"/docs/optimization.html",relativePath:"docs/optimization.md",key:"v-1c00b5c9",path:"/docs/optimization.html",headers:[{level:2,title:"Introducing ZQuery",slug:"introducing-zquery"},{level:2,title:"Building a DataSource",slug:"building-a-datasource"},{level:2,title:"ZQuery constructors and operators",slug:"zquery-constructors-and-operators"},{level:2,title:"Using ZQuery with Caliban",slug:"using-zquery-with-caliban"},{level:2,title:"Using field metadata",slug:"using-field-metadata"},{level:2,title:"@defer support (experimental)",slug:"defer-support-experimental"},{level:3,title:"Usage",slug:"usage"}]},{title:"Relay Connections",frontmatter:{},regularPath:"/docs/relay-connections.html",relativePath:"docs/relay-connections.md",key:"v-56e4d50b",path:"/docs/relay-connections.html",headers:[{level:2,title:"Cursors",slug:"cursors"}]},{title:"Schema comparison",frontmatter:{},regularPath:"/docs/schema-comparison.html",relativePath:"docs/schema-comparison.md",key:"v-4f917bd3",path:"/docs/schema-comparison.html"},{title:"Code generation",frontmatter:{},regularPath:"/docs/server-codegen.html",relativePath:"docs/server-codegen.md",key:"v-6abbdcee",path:"/docs/server-codegen.html",headers:[{level:2,title:"Options",slug:"options"},{level:2,title:"Lazy evaluation",slug:"lazy-evaluation"},{level:2,title:"Newtype declaration",slug:"newtype-declaration"}]},{title:"Schema Reporting",frontmatter:{},regularPath:"/docs/schema-reporting.html",relativePath:"docs/schema-reporting.md",key:"v-87b4d6ae",path:"/docs/schema-reporting.html"},{title:"Stitching",frontmatter:{},regularPath:"/docs/stitching.html",relativePath:"docs/stitching.md",key:"v-ded899ca",path:"/docs/stitching.html",headers:[{level:2,title:"Dependencies",slug:"dependencies"},{level:2,title:"Stitching in Action",slug:"stitching-in-action"},{level:2,title:"Things not yet supported",slug:"things-not-yet-supported"}]},{title:"Schema generation",frontmatter:{},regularPath:"/docs/schema.html",relativePath:"docs/schema.md",key:"v-7bafdcee",path:"/docs/schema.html",headers:[{level:2,title:"Enums, unions, interfaces",slug:"enums-unions-interfaces"},{level:2,title:"Case classes and sealed traits",slug:"case-classes-and-sealed-traits"},{level:3,title:"Auto derivation",slug:"auto-derivation"},{level:3,title:"Semi-auto derivation",slug:"semi-auto-derivation"},{level:3,title:"Combining auto and semi-auto derivation",slug:"combining-auto-and-semi-auto-derivation"},{level:3,title:"Deriving fields from case class methods (Scala 3 only)",slug:"deriving-fields-from-case-class-methods-scala-3-only"},{level:2,title:"Arguments",slug:"arguments"},{level:3,title:"Input objects",slug:"input-objects"},{level:3,title:"@oneOf input objects",slug:"oneof-input-objects"},{level:2,title:"Custom types",slug:"custom-types"},{level:2,title:"Effects",slug:"effects"},{level:2,title:"Subscriptions",slug:"subscriptions"},{level:2,title:"Annotations",slug:"annotations"},{level:2,title:"Java 8 Time types",slug:"java-8-time-types"},{level:2,title:"Using features that are disabled by default",slug:"using-features-that-are-disabled-by-default"},{level:3,title:"SemanticNonNull support",slug:"semanticnonnull-support"},{level:2,title:"Building Schemas by hand",slug:"building-schemas-by-hand"},{level:2,title:"Schema transformations",slug:"schema-transformations"}]},{title:"Getting Started",frontmatter:{},regularPath:"/docs/tools.html",relativePath:"docs/tools.md",key:"v-09883f07",path:"/docs/tools.html",headers:[{level:2,title:"Dependency",slug:"dependency"}]},{title:"FAQ",frontmatter:{},regularPath:"/faq/",relativePath:"faq/README.md",key:"v-40b685e4",path:"/faq/",headers:[{level:3,title:"I don't know where to start 😥",slug:"i-don-t-know-where-to-start-😥"},{level:3,title:"I'm getting a compilation error saying a Schema is missing, but I don't know which one.",slug:"i-m-getting-a-compilation-error-saying-a-schema-is-missing-but-i-don-t-know-which-one"},{level:3,title:"I want to use Caliban, but I use Cats Effect / Monix instead of ZIO.",slug:"i-want-to-use-caliban-but-i-use-cats-effect-monix-instead-of-zio"},{level:3,title:'My query fails with an "Effect failure" error. How can I get more details?',slug:"my-query-fails-with-an-effect-failure-error-how-can-i-get-more-details"},{level:3,title:"I have more than 22 fields in my Query, I can't create a case class for it.",slug:"i-have-more-than-22-fields-in-my-query-i-can-t-create-a-case-class-for-it"},{level:3,title:"How to deal with authentication/authorization?",slug:"how-to-deal-with-authentication-authorization"},{level:3,title:"I have 2 case classes with the same name (different packages). How to avoid conflicts?",slug:"i-have-2-case-classes-with-the-same-name-different-packages-how-to-avoid-conflicts"},{level:3,title:"The auto-generated schema shows a field is nullable, but I want it non-nullable instead.",slug:"the-auto-generated-schema-shows-a-field-is-nullable-but-i-want-it-non-nullable-instead"},{level:3,title:"Can I use a union as input?",slug:"can-i-use-a-union-as-input"},{level:3,title:"How to deal with recursive types?",slug:"how-to-deal-with-recursive-types"},{level:3,title:'I\'m getting a "Method too large" compiler error.',slug:"i-m-getting-a-method-too-large-compiler-error"},{level:3,title:"How can I define a Schema for a Java enum?",slug:"how-can-i-define-a-schema-for-a-java-enum"},{level:3,title:"I don't want to use Throwable as my error type",slug:"i-don-t-want-to-use-throwable-as-my-error-type"},{level:3,title:"My interface is missing from the schema",slug:"my-interface-is-missing-from-the-schema"},{level:3,title:"Can I check that a GraphQL query is valid at compile-time?",slug:"can-i-check-that-a-graphql-query-is-valid-at-compile-time"}]},{title:"Resources",frontmatter:{},regularPath:"/resources/",relativePath:"resources/README.md",key:"v-a971ed74",path:"/resources/",headers:[{level:2,title:"Talks",slug:"talks"},{level:2,title:"Blog Articles",slug:"blog-articles"},{level:2,title:"Related Projects",slug:"related-projects"}]}],themeConfig:{logo:"/caliban.svg",locales:{"/":{selectText:"Language",label:"English",nav:[{text:"Documentation",link:"/docs/"},{text:"Resources",link:"/resources/"},{text:"FAQ",link:"/faq/"},{text:"About",link:"/about/"},{text:"Github",link:"https://github.com/ghostdogpr/caliban"},{text:"Scaladoc",link:"https://javadoc.io/doc/com.github.ghostdogpr/caliban_3/"}],sidebar:{"/docs/":[{title:"Caliban Server",collapsable:!0,sidebarDepth:2,children:["","schema","server-codegen","adapters","middleware","optimization","interop","federation","relay-connections","schema-reporting"]},{title:"Caliban Client",collapsable:!0,sidebarDepth:2,children:["client","client-codegen","laminext"]},{title:"Caliban Tools",collapsable:!0,sidebarDepth:2,children:["tools","stitching","schema-comparison"]},{title:"Examples",path:"examples"}]}}}},locales:{"/":{lang:"en-US",title:"Caliban",description:"Functional GraphQL library for Scala",path:"/"}}};n(235);Gn.component("Badge",()=>Promise.all([n.e(0),n.e(4)]).then(n.bind(null,303))),Gn.component("CodeBlock",()=>Promise.all([n.e(0),n.e(5)]).then(n.bind(null,299))),Gn.component("CodeGroup",()=>Promise.all([n.e(0),n.e(6)]).then(n.bind(null,300)));n(236);var Ts=[{},({Vue:t})=>{t.mixin({computed:{$dataBlock(){return this.$options.__data__block__}}})},{},{}],Ls=[];class Rs extends class{constructor(){this.store=new Gn({data:{state:{}}})}$get(t){return this.store.state[t]}$set(t,e){Gn.set(this.store.state,t,e)}$emit(...t){this.store.$emit(...t)}$on(...t){this.store.$on(...t)}}{}Object.assign(Rs.prototype,{getPageAsyncComponent:ss,getLayoutAsyncComponent:cs,getAsyncComponent:us,getVueComponent:ls});var Is={install(t){const e=new Rs;t.$vuepress=e,t.prototype.$vuepress=e}};function Ms(t,e){const n=e.toLowerCase();return t.options.routes.some(t=>t.path.toLowerCase()===n)}var Ds={props:{pageKey:String,slotKey:{type:String,default:"default"}},render(t){const e=this.pageKey||this.$parent.$page.key;return ps("pageKey",e),Gn.component(e)||Gn.component(e,ss(e)),Gn.component(e)?t(e):t("")}},Ns={functional:!0,props:{slotKey:String,required:!0},render:(t,{props:e,slots:n})=>t("div",{class:["content__"+e.slotKey]},n()[e.slotKey])},Fs={computed:{openInNewWindowTitle(){return this.$themeLocaleConfig.openNewWindowText||"(opens new window)"}}},Us=(n(237),n(238),Object(js.a)(Fs,(function(){var t=this._self._c;return t("span",[t("svg",{staticClass:"icon outbound",attrs:{xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",x:"0px",y:"0px",viewBox:"0 0 100 100",width:"15",height:"15"}},[t("path",{attrs:{fill:"currentColor",d:"M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"}}),this._v(" "),t("polygon",{attrs:{fill:"currentColor",points:"45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"}})]),this._v(" "),t("span",{staticClass:"sr-only"},[this._v(this._s(this.openInNewWindowTitle))])])}),[],!1,null,null,null).exports),zs={functional:!0,render(t,{parent:e,children:n}){if(e._isMounted)return n;e.$once("hook:mounted",()=>{e.$forceUpdate()})}};Gn.config.productionTip=!1,Gn.use(Ha),Gn.use(Is),Gn.mixin(function(t,e,n=Gn){!function(t){t.locales&&Object.keys(t.locales).forEach(e=>{t.locales[e].path=e});Object.freeze(t)}(e),n.$vuepress.$set("siteData",e);const r=new(t(n.$vuepress.$get("siteData"))),o=Object.getOwnPropertyDescriptors(Object.getPrototypeOf(r)),i={};return Object.keys(o).reduce((t,e)=>(e.startsWith("$")&&(t[e]=o[e].get),t),i),{computed:i}}(t=>class{setPage(t){this.__page=t}get $site(){return t}get $themeConfig(){return this.$site.themeConfig}get $frontmatter(){return this.$page.frontmatter}get $localeConfig(){const{locales:t={}}=this.$site;let e,n;for(const r in t)"/"===r?n=t[r]:0===this.$page.path.indexOf(r)&&(e=t[r]);return e||n||{}}get $siteTitle(){return this.$localeConfig.title||this.$site.title||""}get $canonicalUrl(){const{canonicalUrl:t}=this.$page.frontmatter;return"string"==typeof t&&t}get $title(){const t=this.$page,{metaTitle:e}=this.$page.frontmatter;if("string"==typeof e)return e;const n=this.$siteTitle,r=t.frontmatter.home?null:t.frontmatter.title||t.title;return n?r?r+" | "+n:n:r||"VuePress"}get $description(){const t=function(t){if(t){const e=t.filter(t=>"description"===t.name)[0];if(e)return e.content}}(this.$page.frontmatter.meta);return t||(this.$page.frontmatter.description||this.$localeConfig.description||this.$site.description||"")}get $lang(){return this.$page.frontmatter.lang||this.$localeConfig.lang||"en-US"}get $localePath(){return this.$localeConfig.path||"/"}get $themeLocaleConfig(){return(this.$site.themeConfig.locales||{})[this.$localePath]||{}}get $page(){return this.__page?this.__page:function(t,e){for(let n=0;nn||(t.hash?!Gn.$vuepress.$get("disableScrollBehavior")&&{selector:decodeURIComponent(t.hash)}:{x:0,y:0})});!function(t){t.beforeEach((e,n,r)=>{if(Ms(t,e.path))r();else if(/(\/|\.html)$/.test(e.path))if(/\/$/.test(e.path)){const n=e.path.replace(/\/$/,"")+".html";Ms(t,n)?r(n):r()}else r();else{const n=e.path+"/",o=e.path+".html";Ms(t,o)?r(o):Ms(t,n)?r(n):r()}})}(n);const r={};try{await Promise.all(Ts.filter(t=>"function"==typeof t).map(e=>e({Vue:Gn,options:r,router:n,siteData:As,isServer:t})))}catch(t){console.error(t)}return{app:new Gn(Object.assign(r,{router:n,render:t=>t("div",{attrs:{id:"app"}},[t("RouterView",{ref:"layout"}),t("div",{class:"global-ui"},Ls.map(e=>t(e)))])})),router:n}}(!1).then(({app:t,router:e})=>{e.onReady(()=>{t.$mount("#app")})})}]); \ No newline at end of file diff --git a/docs/docs/adapters.html b/docs/docs/adapters.html index c1dc9459e1..b922e7f45f 100644 --- a/docs/docs/adapters.html +++ b/docs/docs/adapters.html @@ -8,7 +8,7 @@ - + @@ -52,7 +52,7 @@ val route = AkkaHttpAdapter.default().makeHttpService(authInterpreter)

Want to use something else? Check make your own adapter section!

Make sure to check the examples to see the adapters in action.

# Make your own adapter

All existing adapters are actually using a common adapter under the hood, called TapirAdapter.

This adapter, available in the caliban-tapir dependency which has the same 3 methods makeHttpService, makeHttpUploadService and makeWebSocketService.

The main differences between these and the methods from the built-in adapters is that they return one or several tapir ServerEndpoint, which you can then pass to a tapir interpreter. The returned ServerEndpoint use RIO[R, *] as an effect type, but you can easily transform it to another effect type. A helper convertHttpEndpointToFuture allows converting the effect type to a scala Future (this is used in the Akka, Pekko, and Play interpreters).

# High-performance QuickAdapter

The QuickAdapter requires minimal setup and uses zio-http (opens new window) -without tapir in order to provide the best possible performance.

# Usage

In order to use it, just add the following to your build.sbt file (no other dependencies required!):

libraryDependencies += "com.github.ghostdogpr" %% "caliban-quick" % "2.8.1"
+without tapir in order to provide the best possible performance.

# Usage

In order to use it, just add the following to your build.sbt file (no other dependencies required!):

libraryDependencies += "com.github.ghostdogpr" %% "caliban-quick" % "2.9.0"
 

By adding import caliban.quick._, we expose a few convenient extension methods on our GraphQL api. For example, we can serve our GraphQL api with minimal setup via a single command:

import caliban._
 import caliban.quick._
@@ -95,6 +95,6 @@
       
       →
     

- + diff --git a/docs/docs/client-codegen.html b/docs/docs/client-codegen.html index 66986492d1..0fb1eec656 100644 --- a/docs/docs/client-codegen.html +++ b/docs/docs/client-codegen.html @@ -8,7 +8,7 @@ - + @@ -38,7 +38,7 @@ Scaladoc (opens new window)

# Code Generation

Caliban provides two sbt plugins to generate your client(s) code.

The first one, named CalibanPlugin, allows you to generate the client code from a schema file or from a server URL, manually or automatically.

The second one, named CompileTimeCalibanPlugin, allows you to generate the client code from your server code. This second "meta" plugin is actually made of two "concrete" plugins, CompileTimeCalibanServerPlugin and CompileTimeCalibanClientPlugin, that you'll -both need to configure in your project to be able to generate you Caliban client code from your Caliban server code.

To use any of these two plugins, you'll first need to add following dependency to your project/plugins.sbt file:

addSbtPlugin("com.github.ghostdogpr" % "caliban-codegen-sbt" % "2.8.1")
+both need to configure in your project to be able to generate you Caliban client code from your Caliban server code.

To use any of these two plugins, you'll first need to add following dependency to your project/plugins.sbt file:

addSbtPlugin("com.github.ghostdogpr" % "caliban-codegen-sbt" % "2.9.0")
 

# CalibanPlugin

The first step for building GraphQL queries with caliban-client is to generate boilerplate code from a GraphQL schema. For that, you need a file containing your schema (if your backend uses caliban, you can get it by calling GraphQL#render on your API).

And enable it in your build.sbt file:

enablePlugins(CalibanPlugin)
 

# From a schema file

At this point, the caliban command will cause any files in src/main/graphql to be translated into a Caliban-generated client library. This happens automatically any time you compile.

By default, all clients are generated with the same client name as the source file, in the caliban top-level package.

In order to supply more configuration options to the code generator, you can use the calibanSettings sbt setting, combined with the calibanSetting function to scope the settings to a particular file:

      // The `file("Service.graphql")` is a path suffix for some file in `src/main/graphql`
       Compile / caliban / calibanSettings += calibanSetting(file("Service.graphql"))(
@@ -140,6 +140,6 @@
       
       →
     

- + diff --git a/docs/docs/client.html b/docs/docs/client.html index f604acbaa5..dbd568dd7b 100644 --- a/docs/docs/client.html +++ b/docs/docs/client.html @@ -8,7 +8,7 @@ - + @@ -36,10 +36,10 @@ Github (opens new window)

# Getting Started

Caliban Client is a module independent from Caliban Server that makes it possible to write GraphQL queries using Scala code in a type-safe and functional fashion. It is built on top of sttp (opens new window), which means you can run requests using the backend of your choice.

Just like the server module, Caliban Client offers a purely functional interface and keeps the boilerplate minimal. It works as follows:

  1. Use the caliban-codegen-sbt tool to generate boilerplate code from a given GraphQL schema
  2. Write your GraphQL queries/mutations by combining helpers from the generated code
  3. Transform your queries/mutations into an sttp request and run them with your preferred backend

# Dependencies

To use caliban-client, add the following dependency to your build.sbt file:

"com.github.ghostdogpr" %% "caliban-client" % "2.8.1"
-

Caliban-client is available for ScalaJS. To use it in a ScalaJS project, instead add this dependency to your build.sbt file:

"com.github.ghostdogpr" %%% "caliban-client" % "2.8.1"
+   (opens new window)

# Getting Started

Caliban Client is a module independent from Caliban Server that makes it possible to write GraphQL queries using Scala code in a type-safe and functional fashion. It is built on top of sttp (opens new window), which means you can run requests using the backend of your choice.

Just like the server module, Caliban Client offers a purely functional interface and keeps the boilerplate minimal. It works as follows:

  1. Use the caliban-codegen-sbt tool to generate boilerplate code from a given GraphQL schema
  2. Write your GraphQL queries/mutations by combining helpers from the generated code
  3. Transform your queries/mutations into an sttp request and run them with your preferred backend

# Dependencies

To use caliban-client, add the following dependency to your build.sbt file:

"com.github.ghostdogpr" %% "caliban-client" % "2.9.0"
+

Caliban-client is available for ScalaJS. To use it in a ScalaJS project, instead add this dependency to your build.sbt file:

"com.github.ghostdogpr" %%% "caliban-client" % "2.9.0"
 

# Code generation

Caliban provides several ways to generate the boilerplate code. To get started, we are going to generate it by running a -simple sbt command, but you can look at the Code generation page for more options.

You'll first need to add following dependency to your project/plugins.sbt file:

addSbtPlugin("com.github.ghostdogpr" % "caliban-codegen-sbt" % "2.8.1")
+simple sbt command, but you can look at the Code generation page for more options.

You'll first need to add following dependency to your project/plugins.sbt file:

addSbtPlugin("com.github.ghostdogpr" % "caliban-codegen-sbt" % "2.9.0")
 

And to enable the plugin in your build.sbt file:

enablePlugins(CalibanPlugin)
 

Then, you can run the following command in your sbt.

calibanGenClient schemaPath outputPath
 
@@ -101,6 +101,6 @@
       
       →
     

- + diff --git a/docs/docs/examples.html b/docs/docs/examples.html index d49d0234ca..452f0c2cbe 100644 --- a/docs/docs/examples.html +++ b/docs/docs/examples.html @@ -8,7 +8,7 @@ - + @@ -41,6 +41,6 @@

- + diff --git a/docs/docs/federation.html b/docs/docs/federation.html index 2d4ef48c3a..0d4e44a41f 100644 --- a/docs/docs/federation.html +++ b/docs/docs/federation.html @@ -8,7 +8,7 @@ - + @@ -36,7 +36,7 @@ Github (opens new window)

# Federation

Federation is an optional module which can be included in your configuration to enroll with a federated schema.

# Dependencies

caliban-federation only depends on caliban-core and is very unobtrusive.

To use, add the following dependency to your build.sbt file:

"com.github.ghostdogpr" %% "caliban-federation" % "2.8.1"
+   (opens new window)

# Federation

Federation is an optional module which can be included in your configuration to enroll with a federated schema.

# Dependencies

caliban-federation only depends on caliban-core and is very unobtrusive.

To use, add the following dependency to your build.sbt file:

"com.github.ghostdogpr" %% "caliban-federation" % "2.9.0"
 

# Federating

Federation allows graphs to become part of a larger graph without having to share models or create brittle schema stitching code at the gateway level.

You can read more about federation and why it may be useful here (opens new window).

Federation creates a wrapper over your existing schema so that it can add the necessary hooks to support interaction with the gateway.

If you already have a graph you can add federation simply by adding the federated annotation:

import caliban.federation.v1._
@@ -105,6 +105,6 @@
       
       →
     

- + diff --git a/docs/docs/index.html b/docs/docs/index.html index 86655b410a..128c8d0058 100644 --- a/docs/docs/index.html +++ b/docs/docs/index.html @@ -8,7 +8,7 @@ - + @@ -36,7 +36,7 @@ Github (opens new window)

# Getting Started

Caliban is a purely functional library for creating GraphQL servers and clients in Scala.

For more details on Caliban Client, see the dedicated section. The rest of this page focuses on the backend part of the library.

The design principles of Caliban are the following:

# A simple schema

First, add the following dependency to your build.sbt file:

"com.github.ghostdogpr" %% "caliban" % "2.8.1"
+   (opens new window)

# Getting Started

Caliban is a purely functional library for creating GraphQL servers and clients in Scala.

For more details on Caliban Client, see the dedicated section. The rest of this page focuses on the backend part of the library.

The design principles of Caliban are the following:

# A simple schema

First, add the following dependency to your build.sbt file:

"com.github.ghostdogpr" %% "caliban" % "2.9.0"
 

Creating a GraphQL API with Caliban is as simple as creating a case class in Scala. Indeed, the whole GraphQL schema will be derived from a case class hierarchy (its fields and the other types it references), and the resolver is just an instance of that case class.

Let's say we have a class Character and 2 functions: getCharacters and getCharacter:

case class Character(name: String, age: Int)
 
@@ -66,31 +66,31 @@
   character(name: String!): Character
 }
 

# Serving over HTTP

Once you have your API object, you can turn it into an interpreter (api.interpreter) and start processing requests (interpreter.execute). -The interpreter is not tied any web framework, so you are free to expose this function using the protocol and library of your choice.

The easiest (and most performant!) way to expose your API over HTTP is to use the optional caliban-quick module based on zio-http (opens new window).

"com.github.ghostdogpr" %% "caliban-quick"  % "2.8.1"
+The interpreter is not tied any web framework, so you are free to expose this function using the protocol and library of your choice.

The easiest (and most performant!) way to expose your API over HTTP is to use the optional caliban-quick module based on zio-http (opens new window).

"com.github.ghostdogpr" %% "caliban-quick"  % "2.9.0"
 

You can then serve your GraphQL API over HTTP using a single command:

import caliban.quick._ // adds extension methods to `api`
 
 api.unsafe.runServer(
   port = 8080,
   apiPath = "/api/graphql",
 )
-

And that's it - now you have a fully functional GraphQL server running on port 8080!

# Interop with 3rd-party libraries

If you have any specific server requirements or need to interop with other libraries, Caliban offers a wide range of modules to help you do that.

"com.github.ghostdogpr" %% "caliban-http4s"     % "2.8.1" // routes for http4s
-"com.github.ghostdogpr" %% "caliban-akka-http"  % "2.8.1" // routes for akka-http
-"com.github.ghostdogpr" %% "caliban-pekko-http" % "2.8.1" // routes for pekko-http
-"com.github.ghostdogpr" %% "caliban-play"       % "2.8.1" // routes for play
+

And that's it - now you have a fully functional GraphQL server running on port 8080!

# Interop with 3rd-party libraries

If you have any specific server requirements or need to interop with other libraries, Caliban offers a wide range of modules to help you do that.

"com.github.ghostdogpr" %% "caliban-http4s"     % "2.9.0" // routes for http4s
+"com.github.ghostdogpr" %% "caliban-akka-http"  % "2.9.0" // routes for akka-http
+"com.github.ghostdogpr" %% "caliban-pekko-http" % "2.9.0" // routes for pekko-http
+"com.github.ghostdogpr" %% "caliban-play"       % "2.9.0" // routes for play
 
-"com.github.ghostdogpr" %% "caliban-cats"       % "2.8.1" // interop with cats-effect
-"com.github.ghostdogpr" %% "caliban-monix"      % "2.8.1" // interop with monix
-"com.github.ghostdogpr" %% "caliban-tapir"      % "2.8.1" // interop with tapir
+"com.github.ghostdogpr" %% "caliban-cats"       % "2.9.0" // interop with cats-effect
+"com.github.ghostdogpr" %% "caliban-monix"      % "2.9.0" // interop with monix
+"com.github.ghostdogpr" %% "caliban-tapir"      % "2.9.0" // interop with tapir
 
-"com.github.ghostdogpr" %% "caliban-federation" % "2.8.1" // apollo federation
-"com.github.ghostdogpr" %% "caliban-reporting"  % "2.8.1" // apollo schema reporting
-"com.github.ghostdogpr" %% "caliban-tracing"    % "2.8.1" // open-telemetry
+"com.github.ghostdogpr" %% "caliban-federation" % "2.9.0" // apollo federation
+"com.github.ghostdogpr" %% "caliban-reporting"  % "2.9.0" // apollo schema reporting
+"com.github.ghostdogpr" %% "caliban-tracing"    % "2.9.0" // open-telemetry
 

# Where to go next?

The rest of the documentation covers in details how to create schemas, customize and optimize query processing, expose APIs, and much more.

If you'd like to see a more detailed version of this tutorial, check out this Beginner's Guide to GraphQL in Scala (opens new window). If you prefer looking at some code first, check this list of examples (opens new window).

If you have any questions, just come to the Discord channel (opens new window)!

- + diff --git a/docs/docs/interop.html b/docs/docs/interop.html index a871c3d492..a7b4306efc 100644 --- a/docs/docs/interop.html +++ b/docs/docs/interop.html @@ -8,7 +8,7 @@ - + @@ -249,6 +249,6 @@ →

- + diff --git a/docs/docs/laminext.html b/docs/docs/laminext.html index 77c3097f13..b7bb41e026 100644 --- a/docs/docs/laminext.html +++ b/docs/docs/laminext.html @@ -8,7 +8,7 @@ - + @@ -37,7 +37,7 @@ (opens new window)

# Laminext Integration

If you are using the Scala.js framework Laminar (opens new window), there is a module that makes the integration even nicer, with support for subscriptions. -It is depending on Laminext (opens new window), a library that provides nice little helpers for Laminar, in particular for using Fetch and WebSocket.

To use it, import the caliban-client-laminext module:

"com.github.ghostdogpr" %%% "caliban-client-laminext" % "2.8.1"
+It is depending on Laminext (opens new window), a library that provides nice little helpers for Laminar, in particular for using Fetch and WebSocket.

To use it, import the caliban-client-laminext module:

"com.github.ghostdogpr" %%% "caliban-client-laminext" % "2.9.0"
 

Add the following import to your code:

import caliban.client.laminext._
 

This import adds an extension method toEventStream(uri) to SelectionBuilder, which is similar to toRequest except it creates an EventStream instead of an sttp Request.

val characters: Var[List[String]] = Var(Nil)
 
@@ -69,6 +69,6 @@
       
       →
     

- + diff --git a/docs/docs/middleware.html b/docs/docs/middleware.html index 0ccd6af589..d5a45465d3 100644 --- a/docs/docs/middleware.html +++ b/docs/docs/middleware.html @@ -8,7 +8,7 @@ - + @@ -171,7 +171,7 @@ to fields. In this case the field resolver will override the type cost, however if there is no field cost then the type cost will be used. We may also specify a "multipliers" argument when using arguments. This will match the argument names and use numeric argument values to multiply the base value. In the above case this means that a query that specifies a limit of 10 for the spokenLines field will have the base field cost multipled by 10 resulting in a total cost -of execution of 1000

# OpenTelemetry Tracing

Caliban ships with support for OpenTelemetry tracing via integration with zio-telemetry (opens new window) in the caliban-tracing package.

In order to use tracing, first add caliban-tracing to your built.sbt.

"com.github.ghostdogpr" %% "caliban-tracing" % "2.8.1"
+of execution of 1000

# OpenTelemetry Tracing

Caliban ships with support for OpenTelemetry tracing via integration with zio-telemetry (opens new window) in the caliban-tracing package.

In order to use tracing, first add caliban-tracing to your built.sbt.

"com.github.ghostdogpr" %% "caliban-tracing" % "2.9.0"
 

Then add it to your schema as any other wrapper:

import caliban.tracing.TracingWrapper
 import zio.telemetry.opentelemetry.Tracing
 
@@ -192,6 +192,6 @@
       
       →
     

- + diff --git a/docs/docs/optimization.html b/docs/docs/optimization.html index a49c0f5282..ec16758c6d 100644 --- a/docs/docs/optimization.html +++ b/docs/docs/optimization.html @@ -8,7 +8,7 @@ - + @@ -162,6 +162,6 @@ →

- + diff --git a/docs/docs/relay-connections.html b/docs/docs/relay-connections.html index 537cc5cc95..0d54f7e0d6 100644 --- a/docs/docs/relay-connections.html +++ b/docs/docs/relay-connections.html @@ -8,7 +8,7 @@ - + @@ -142,6 +142,6 @@ →

- + diff --git a/docs/docs/schema-comparison.html b/docs/docs/schema-comparison.html index 61df5d1777..8d815f8ed9 100644 --- a/docs/docs/schema-comparison.html +++ b/docs/docs/schema-comparison.html @@ -8,7 +8,7 @@ - + @@ -75,6 +75,6 @@ →

- + diff --git a/docs/docs/schema-reporting.html b/docs/docs/schema-reporting.html index 2b65d7c988..b5594a4ee5 100644 --- a/docs/docs/schema-reporting.html +++ b/docs/docs/schema-reporting.html @@ -8,7 +8,7 @@ - + @@ -69,6 +69,6 @@ →

- + diff --git a/docs/docs/schema.html b/docs/docs/schema.html index fa259cb93d..78efbc332d 100644 --- a/docs/docs/schema.html +++ b/docs/docs/schema.html @@ -8,7 +8,7 @@ - + @@ -238,6 +238,6 @@ →

- + diff --git a/docs/docs/server-codegen.html b/docs/docs/server-codegen.html index 959ba2fed8..0fd811f4b9 100644 --- a/docs/docs/server-codegen.html +++ b/docs/docs/server-codegen.html @@ -8,7 +8,7 @@ - + @@ -36,7 +36,7 @@ Github (opens new window)

# Code generation

If you want a workflow where you first edit a GraphQL schema file, and then generate type-safe server stubs, Caliban has your back.

You'll first need to add the following dependency to your project/plugins.sbt file:

addSbtPlugin("com.github.ghostdogpr" % "caliban-codegen-sbt" % "2.8.1")
+   (opens new window)

# Code generation

If you want a workflow where you first edit a GraphQL schema file, and then generate type-safe server stubs, Caliban has your back.

You'll first need to add the following dependency to your project/plugins.sbt file:

addSbtPlugin("com.github.ghostdogpr" % "caliban-codegen-sbt" % "2.9.0")
 

You then enable it in your build.sbt file:

import _root_.caliban.tools.Codegen
 
 lazy val myproject = project
@@ -129,6 +129,6 @@
       
       →
     

- + diff --git a/docs/docs/stitching.html b/docs/docs/stitching.html index 039c8392e3..3a44547cf5 100644 --- a/docs/docs/stitching.html +++ b/docs/docs/stitching.html @@ -8,7 +8,7 @@ - + @@ -36,7 +36,7 @@ Github (opens new window)

# Stitching

Stitching is a part of caliban-tools which can be used to use parts of another GraphQL API from an API you're building in situations where using Apollo federation isn't an option. You can also use it to fully subsume and proxy another GraphQL schema.

In general, Federation should be your preferred choice.

You should also be careful when using stitching since it's very easy to pull in large parts of an external schema's types and structure into your API. This can make it error prone since the likelihood that you'll get type clashes between your API and the API you're stitching in quickly increases.

# Dependencies

In order to use stitching, add caliban-tools to your dependencies:

"com.github.ghostdogpr" %% "caliban-tools" % "2.8.1"
+   (opens new window)

# Stitching

Stitching is a part of caliban-tools which can be used to use parts of another GraphQL API from an API you're building in situations where using Apollo federation isn't an option. You can also use it to fully subsume and proxy another GraphQL schema.

In general, Federation should be your preferred choice.

You should also be careful when using stitching since it's very easy to pull in large parts of an external schema's types and structure into your API. This can make it error prone since the likelihood that you'll get type clashes between your API and the API you're stitching in quickly increases.

# Dependencies

In order to use stitching, add caliban-tools to your dependencies:

"com.github.ghostdogpr" %% "caliban-tools" % "2.9.0"
 

# Stitching in Action

Let's start out by defining our API. We'll have AppUser profiles, that has a linked featuredRepository. For the featuredRepository, we want to leverage Github's GraphQL API (opens new window).

import caliban._
 import caliban.schema._
 import caliban.schema.Schema.auto._
@@ -181,6 +181,6 @@
       
       →
     

- + diff --git a/docs/docs/tools.html b/docs/docs/tools.html index 4afda1c8a6..ac22f37966 100644 --- a/docs/docs/tools.html +++ b/docs/docs/tools.html @@ -8,7 +8,7 @@ - + @@ -36,7 +36,7 @@ Github (opens new window)

# Getting Started

Caliban comes with a module called caliban-tools that exposes some useful features:

  • all the code generation features from caliban-codegen-sbt, so that you can use them without sbt: see caliban.tools.Codegen.
  • a client for GraphQL introspection: see caliban.tools.IntrospectionClient.
  • utilities for stitching GraphQL schemas.
  • a way to compare GraphQL schemas, whether they come from Caliban or a remote server.

# Dependency

"com.github.ghostdogpr" %% "caliban-tools" % "2.8.1"
+   (opens new window)

# Getting Started

Caliban comes with a module called caliban-tools that exposes some useful features:

  • all the code generation features from caliban-codegen-sbt, so that you can use them without sbt: see caliban.tools.Codegen.
  • a client for GraphQL introspection: see caliban.tools.IntrospectionClient.
  • utilities for stitching GraphQL schemas.
  • a way to compare GraphQL schemas, whether they come from Caliban or a remote server.

# Dependency

"com.github.ghostdogpr" %% "caliban-tools" % "2.9.0"
 
- + diff --git a/docs/faq/index.html b/docs/faq/index.html index 94b51f9fc0..42ffa6a712 100644 --- a/docs/faq/index.html +++ b/docs/faq/index.html @@ -8,7 +8,7 @@ - + @@ -82,6 +82,6 @@ } }""")
- + diff --git a/docs/index.html b/docs/index.html index 0014a7b0de..da12bd8b5a 100644 --- a/docs/index.html +++ b/docs/index.html @@ -8,7 +8,7 @@ - + @@ -43,6 +43,6 @@

Get Started →

High performance

While all public interfaces are pure and immutable, the library's internals are optimized for speed.

Minimal boilerplate

No need to manually define schemas for every type in your API. Let the compiler handle the tedious work.

Excellent interoperability

Out-of-the-box support for major HTTP server libraries, effect types, JSON libraries, and more.

- + diff --git a/docs/resources/index.html b/docs/resources/index.html index 69834b1298..71f8dc490d 100644 --- a/docs/resources/index.html +++ b/docs/resources/index.html @@ -8,7 +8,7 @@ - + @@ -38,6 +38,6 @@ Scaladoc (opens new window)

# Resources

# Talks

# Blog Articles

- +