From 879b6e5ab7d3e7439a01000190526cf803002f89 Mon Sep 17 00:00:00 2001 From: Pierre Ricadat Date: Fri, 5 Nov 2021 07:12:13 +0000 Subject: [PATCH] [ci skip] update docs --- docs/404.html | 6 +++--- docs/about/index.html | 4 ++-- docs/assets/js/{10.9820a74b.js => 10.8c22ee5c.js} | 2 +- docs/assets/js/{11.f3bf0108.js => 11.6f1922be.js} | 2 +- docs/assets/js/{12.c729c0a9.js => 12.88935583.js} | 2 +- docs/assets/js/{13.4eb72b62.js => 13.550a76f2.js} | 2 +- docs/assets/js/{14.51224088.js => 14.22d76291.js} | 2 +- docs/assets/js/{15.126379cb.js => 15.23a221ff.js} | 2 +- docs/assets/js/{16.9e329d2b.js => 16.2d4ba3db.js} | 2 +- docs/assets/js/17.df959ed2.js | 1 - docs/assets/js/17.eff2b8a2.js | 1 + docs/assets/js/{18.c4fbc130.js => 18.77b2e100.js} | 2 +- docs/assets/js/{19.589dd5a6.js => 19.3f45935a.js} | 2 +- docs/assets/js/2.942dda74.js | 1 + docs/assets/js/2.caf3e0bc.js | 1 - docs/assets/js/{20.daa52ffd.js => 20.c7598b24.js} | 2 +- docs/assets/js/{21.6563d4da.js => 21.2cc8bcb9.js} | 2 +- docs/assets/js/{22.724ace4d.js => 22.40e3cec2.js} | 2 +- docs/assets/js/{3.cc5ee1dd.js => 3.831b4f47.js} | 2 +- docs/assets/js/{4.b5c5d85a.js => 4.9c0d3927.js} | 2 +- docs/assets/js/5.8fb2962b.js | 1 + docs/assets/js/5.aedbb9bc.js | 1 - docs/assets/js/{6.7dd3e1f3.js => 6.7a505dc8.js} | 2 +- docs/assets/js/{7.00cd415f.js => 7.1ebac3c6.js} | 2 +- docs/assets/js/{8.17de77bc.js => 8.709919e3.js} | 2 +- docs/assets/js/{9.3d572142.js => 9.8f91e237.js} | 2 +- docs/assets/js/app.bdde3623.js | 8 -------- docs/assets/js/app.dc43ffe4.js | 8 ++++++++ docs/docs/client.html | 4 ++-- docs/docs/examples.html | 4 ++-- docs/docs/federation.html | 4 ++-- docs/docs/index.html | 4 ++-- docs/docs/interop.html | 4 ++-- docs/docs/introspection.html | 4 ++-- docs/docs/middleware.html | 4 ++-- docs/docs/optimization.html | 4 ++-- docs/docs/schema.html | 7 ++++--- docs/docs/stitching.html | 4 ++-- docs/docs/tools.html | 4 ++-- docs/docs/validation.html | 4 ++-- docs/faq/index.html | 4 ++-- docs/index.html | 4 ++-- docs/resources/index.html | 4 ++-- 43 files changed, 66 insertions(+), 65 deletions(-) rename docs/assets/js/{10.9820a74b.js => 10.8c22ee5c.js} (99%) rename docs/assets/js/{11.f3bf0108.js => 11.6f1922be.js} (97%) rename docs/assets/js/{12.c729c0a9.js => 12.88935583.js} (99%) rename docs/assets/js/{13.4eb72b62.js => 13.550a76f2.js} (99%) rename docs/assets/js/{14.51224088.js => 14.22d76291.js} (89%) rename docs/assets/js/{15.126379cb.js => 15.23a221ff.js} (99%) rename docs/assets/js/{16.9e329d2b.js => 16.2d4ba3db.js} (99%) delete mode 100644 docs/assets/js/17.df959ed2.js create mode 100644 docs/assets/js/17.eff2b8a2.js rename docs/assets/js/{18.c4fbc130.js => 18.77b2e100.js} (99%) rename docs/assets/js/{19.589dd5a6.js => 19.3f45935a.js} (98%) create mode 100644 docs/assets/js/2.942dda74.js delete mode 100644 docs/assets/js/2.caf3e0bc.js rename docs/assets/js/{20.daa52ffd.js => 20.c7598b24.js} (95%) rename docs/assets/js/{21.6563d4da.js => 21.2cc8bcb9.js} (99%) rename docs/assets/js/{22.724ace4d.js => 22.40e3cec2.js} (97%) rename docs/assets/js/{3.cc5ee1dd.js => 3.831b4f47.js} (62%) rename docs/assets/js/{4.b5c5d85a.js => 4.9c0d3927.js} (67%) create mode 100644 docs/assets/js/5.8fb2962b.js delete mode 100644 docs/assets/js/5.aedbb9bc.js rename docs/assets/js/{6.7dd3e1f3.js => 6.7a505dc8.js} (81%) rename docs/assets/js/{7.00cd415f.js => 7.1ebac3c6.js} (58%) rename docs/assets/js/{8.17de77bc.js => 8.709919e3.js} (94%) rename docs/assets/js/{9.3d572142.js => 9.8f91e237.js} (99%) delete mode 100644 docs/assets/js/app.bdde3623.js create mode 100644 docs/assets/js/app.dc43ffe4.js diff --git a/docs/404.html b/docs/404.html index b65adf07b0..fb8bbe595e 100644 --- a/docs/404.html +++ b/docs/404.html @@ -8,13 +8,13 @@ - + -

404

There's nothing here.
+ - + diff --git a/docs/about/index.html b/docs/about/index.html index 3a0362d8d1..4b818be75e 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 developed by Pierre Ricadat aka @ghostdogpr (opens new window).

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

Thanks:

- + diff --git a/docs/assets/js/10.9820a74b.js b/docs/assets/js/10.8c22ee5c.js similarity index 99% rename from docs/assets/js/10.9820a74b.js rename to docs/assets/js/10.8c22ee5c.js index 0926f9da63..5318a4650e 100644 --- a/docs/assets/js/10.9820a74b.js +++ b/docs/assets/js/10.8c22ee5c.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[10],{382:function(t,a,e){"use strict";e.r(a);var s=e(46),n=Object(s.a)({},(function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"graphql-client"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#graphql-client"}},[t._v("#")]),t._v(" GraphQL Client")]),t._v(" "),e("p",[e("strong",[t._v("Caliban-client")]),t._v(" is a module independent from Caliban that makes it possible to write GraphQL queries using Scala code in a type-safe and functional fashion. It is built on top of "),e("a",{attrs:{href:"https://github.com/softwaremill/sttp",target:"_blank",rel:"noopener noreferrer"}},[t._v("sttp"),e("OutboundLink")],1),t._v(", which means you can run requests using the backend of your choice.")]),t._v(" "),e("p",[t._v("Just like Caliban, "),e("code",[t._v("caliban-client")]),t._v(" offers a purely functional interface and keeps the boilerplate minimal. It works as follows:")]),t._v(" "),e("ol",[e("li",[t._v("Use the "),e("code",[t._v("caliban-codegen-sbt")]),t._v(" tool to generate boilerplate code from a given GraphQL schema")]),t._v(" "),e("li",[t._v("Write your GraphQL query/mutation by combining helpers from the generated code")]),t._v(" "),e("li",[t._v("Transform your query/mutation into an "),e("code",[t._v("sttp")]),t._v(" request and run it with your preferred backend")])]),t._v(" "),e("h2",{attrs:{id:"dependencies"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#dependencies"}},[t._v("#")]),t._v(" Dependencies")]),t._v(" "),e("p",[t._v("To use "),e("code",[t._v("caliban-client")]),t._v(", add the following line in your "),e("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v('libraryDependencies += "com.github.ghostdogpr" %% "caliban-client" % "1.2.1"\n')])])]),e("p",[t._v("Caliban-client is available for ScalaJS. To use it in a ScalaJS project, instead add this line to your "),e("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v('libraryDependencies += "com.github.ghostdogpr" %%% "caliban-client" % "1.2.1"\n')])])]),e("h2",{attrs:{id:"code-generation"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#code-generation"}},[t._v("#")]),t._v(" Code generation")]),t._v(" "),e("p",[t._v("Caliban provides two sbt plugins to generate your client(s) code.")]),t._v(" "),e("p",[t._v("The first one, named "),e("code",[t._v("CalibanPlugin")]),t._v(", allows you to generate the client code from a schema file or from a server URL.")]),t._v(" "),e("p",[t._v("The second one, named "),e("code",[t._v("CompileTimeCalibanPlugin")]),t._v(", allows you to generate the client code from your server code."),e("br"),t._v('\nThis second "meta" plugin is actually made of two "concrete" plugins, '),e("code",[t._v("CompileTimeCalibanServerPlugin")]),t._v(" and "),e("code",[t._v("CompileTimeCalibanClientPlugin")]),t._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.")]),t._v(" "),e("p",[t._v("To use any of these two plugins, you'll first need to add following dependency to your "),e("code",[t._v("project/plugins.sbt")]),t._v(" file:")]),t._v(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[t._v("addSbtPlugin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),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("%")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-codegen-sbt"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1.2.1"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h3",{attrs:{id:"calibanplugin"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#calibanplugin"}},[t._v("#")]),t._v(" CalibanPlugin")]),t._v(" "),e("p",[t._v("The first step for building GraphQL queries with "),e("code",[t._v("caliban-client")]),t._v(" is to generate boilerplate code from a GraphQL schema. For that, you need a file containing your schema (if your backend uses "),e("code",[t._v("caliban")]),t._v(", you can get it by calling "),e("code",[t._v("GraphQL#render")]),t._v(" on your API).")]),t._v(" "),e("p",[t._v("And enable it in your "),e("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[t._v("enablePlugins"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CalibanPlugin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h4",{attrs:{id:"from-a-schema-file"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#from-a-schema-file"}},[t._v("#")]),t._v(" From a schema file")]),t._v(" "),e("p",[t._v("At this point, the "),e("code",[t._v("caliban")]),t._v(" command will cause any files in "),e("code",[t._v("src/main/graphql")]),t._v(" to be translated into a Caliban-generated client library. This happens automatically any time you "),e("code",[t._v("compile")]),t._v(".")]),t._v(" "),e("p",[t._v("By default, all clients are generated with the same client name as the source file, in the "),e("code",[t._v("caliban")]),t._v(" top-level package.")]),t._v(" "),e("p",[t._v("In order to supply more configuration options to the code generator, you can use the "),e("code",[t._v("calibanSettings")]),t._v(" sbt setting, combined with the "),e("code",[t._v("calibanSetting")]),t._v(" function to scope the settings to a particular file:")]),t._v(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// The `file("Service.graphql")` is a path suffix for some file in `src/main/graphql`')]),t._v("\n Compile "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" caliban "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" calibanSettings "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" calibanSetting"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("file"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Service.graphql"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n cs "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n cs"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("packageName"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.example.graphql.client"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("scalarMapping"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"LanguageCode"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.example.models.LanguageCode"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("scalarMapping"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Timestamp"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"java.sql.Timestamp"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"DayOfWeek"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"java.time.DayOfWeek"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"IntRange"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.tminglei.slickpg.Range[Int]"')]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("imports"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.example.graphql.client.implicits._"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h4",{attrs:{id:"from-a-server-url"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#from-a-server-url"}},[t._v("#")]),t._v(" From a server URL")]),t._v(" "),e("p",[t._v("The "),e("code",[t._v("calibanSetting")]),t._v(" function also permits generating clients for supplied "),e("code",[t._v("url")]),t._v("'s:")]),t._v(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[t._v(" Compile "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" caliban "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" calibanSettings "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" calibanSetting"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("url"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://my-example-service/graphql"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n cs "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n cs"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("clientName"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ExampleServiceClient"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("packageName"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.example.graphql.client"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h4",{attrs:{id:"calibansetting-config-parameters"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#calibansetting-config-parameters"}},[t._v("#")]),t._v(" "),e("code",[t._v("calibanSetting")]),t._v(" config parameters")]),t._v(" "),e("p",[t._v("The settings available on the "),e("code",[t._v("cs")]),t._v(" ("),e("code",[t._v("CalibanSettings")]),t._v(") builder are:")]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v(" def scalafmtPath(path: String): CalibanSettings // Path to a scalafmt config (default: .scalafmt.conf)\n def packageName(name: String): CalibanSettings // Which package to put the generated clients in (default: caliban)\n def genView(value: Boolean): CalibanSettings // Provide a case class and helper method to select all fields on an object (default: false)\n def scalarMapping(mapping: (String,String)*): CalibanSettings // A mapping from GraphQL scalar types to JVM types, as unknown scalar types are represented as String by default.\n def imports(values: String*): CalibanSettings // A list of imports to be added to the top of a generated client\n def splitFiles(value: Boolean): CalibanSettings // Split single client object into multiple files (default: false)\n def enableFmt(value: Boolean): CalibanSettings // Enable code formatting with scalafmt (default: true)\n def extensibleEnums(value: Boolean): CalibanSettings // Generate a fallback case class for unknown enum values (default: false)\n\n // Only defined for `url` settings, for use in supplying extra headers when fetching the schema itself\n def headers(pairs: (String,String)*): CalibanSettings\n")])])]),e("h4",{attrs:{id:"calibangenclient"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#calibangenclient"}},[t._v("#")]),t._v(" "),e("code",[t._v("calibanGenClient")])]),t._v(" "),e("p",[t._v("If you prefer to generate the client explicitly rather than automatically, you can use "),e("code",[t._v("calibanGenClient")]),t._v(" on the SBT CLI as follows:")]),t._v(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[t._v("calibanGenClient schemaPath outputPath "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("scalafmtPath path"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("headers name"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("value"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("name2"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("value2"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("genView "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("scalarMappings gqlType"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("f"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("q"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("d"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Type"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("gqlType2"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("f"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("q"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("d"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Type2"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("imports a"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("b"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("c"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("c"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("d"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("E"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("splitFiles "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("enableFmt "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\ncalibanGenClient project"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("schema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("graphql src"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("main"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("client"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("Client"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("scala "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("genView "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v(" \n")])])]),e("p",[t._v("This command will generate a Scala file in "),e("code",[t._v("outputPath")]),t._v(" containing helper functions for all the types defined in the provided GraphQL schema defined at "),e("code",[t._v("schemaPath")]),t._v(".\nIf you need to disable generating clients from "),e("code",[t._v("src/main/graphql")]),t._v(", please include "),e("code",[t._v("Compile / caliban / calibanGenerator := Seq.empty")]),t._v(" in your project settings.\nInstead of a file, you can provide a URL and the schema will be obtained using introspection.\nThe generated code will be formatted with Scalafmt using the configuration defined by "),e("code",[t._v("--scalafmtPath")]),t._v(" option (default: "),e("code",[t._v(".scalafmt.conf")]),t._v(").\nIf you provide a URL for "),e("code",[t._v("schemaPath")]),t._v(", you can provide request headers with "),e("code",[t._v("--headers")]),t._v(" option.\nThe package of the generated code is derived from the folder of "),e("code",[t._v("outputPath")]),t._v(".\nThis can be overridden by providing an alternative package with the "),e("code",[t._v("--packageName")]),t._v("\noption.\nThe generated object name is derived from "),e("code",[t._v("outputPath")]),t._v(" file name but can be overridden with the "),e("code",[t._v("--clientName")]),t._v(" option.\nProvide "),e("code",[t._v("--genView true")]),t._v(" option if you want to generate a view for the GraphQL types.\nIf you want to force a mapping between a GraphQL type and a Scala class (such as scalars), you can use the\n"),e("code",[t._v("--scalarMappings")]),t._v(" option. Also you can add imports for example for your ArgEncoder implicits by providing "),e("code",[t._v("--imports")]),t._v(" option.\nUse the "),e("code",[t._v("--splitFiles true")]),t._v(" option if you want to generate multiple files within the same package instead of a single file.\nIn this case the filename part of the "),e("code",[t._v("outputPath")]),t._v(" will be ignored, but the value will still be used to determine the mandatory package name and the destination directory.\nThis can be helpful with large GraphQL schemas and incremental compilation.\nProvide "),e("code",[t._v("--enableFmt false")]),t._v(" option if you don't need to format generated files.\nProvide "),e("code",[t._v("--extensibleEnums true")]),t._v(" option if you want to generate a fallback case class for unknown enum values.")]),t._v(" "),e("h3",{attrs:{id:"compiletimecalibanplugin"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#compiletimecalibanplugin"}},[t._v("#")]),t._v(" CompileTimeCalibanPlugin")]),t._v(" "),e("p",[t._v("As mentioned in the introduction of the "),e("a",{attrs:{href:"#code-generation"}},[t._v("Code Generation")]),t._v(' chapter, this "meta" plugin is actually made of two "concrete" sbt plugins, '),e("code",[t._v("CompileTimeCalibanServerPlugin")]),t._v(" and "),e("code",[t._v("CompileTimeCalibanClientPlugin")]),t._v(",\nthat you'll both need to configure in your project be able to generate your Caliban client code from your Caliban server code..")]),t._v(" "),e("p",[t._v("You can find a demo project using this plugin here: "),e("a",{attrs:{href:"https://github.com/guizmaii/poc_compile_time_caliban_client_generation",target:"_blank",rel:"noopener noreferrer"}},[t._v("Demo project"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("To generate the Caliban client code from you Caliban server code, you need to do two things:")]),t._v(" "),e("ol",[e("li",[e("p",[t._v("Tell to the plugin where your Caliban "),e("code",[t._v("GraphQL[R]")]),t._v(" instances for which you want to generate a client are and configure the client code generator."),e("br"),t._v("\nHow to configure this is explained in the following "),e("a",{attrs:{href:"#configure-the-server-side"}},[t._v("Configure the server side")]),t._v(" chapter.")])]),t._v(" "),e("li",[e("p",[t._v("Tell to the plugin where you want to generate your client(s)."),e("br"),t._v("\nHow to configure this is explained in the following "),e("a",{attrs:{href:"#configure-the-client-side"}},[t._v("Configure the client side")]),t._v(" chapter.")])])]),t._v(" "),e("h4",{attrs:{id:"configure-the-server-side"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#configure-the-server-side"}},[t._v("#")]),t._v(" Configure the server side")]),t._v(" "),e("p",[t._v("First, you'll need to activate the "),e("code",[t._v("CompileTimeCalibanServerPlugin")]),t._v(" plugin in all the sbt modules of your project containing a "),e("code",[t._v("GraphQL[R]")]),t._v(" instance for which you want to generate a client.")]),t._v(" "),e("p",[t._v("Let's say you have an "),e("code",[t._v("api")]),t._v(" sbt module defined in your "),e("code",[t._v("build.sbt")]),t._v(" which contains your Caliban server code:")]),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 keyword"}},[t._v("lazy")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n project\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("enablePlugins"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CompileTimeCalibanServerPlugin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v('Now, you need to tell to the "server side" plugin where is your '),e("code",[t._v("GraphQL[R]")]),t._v(" instance for which you want to generate a client."),e("br"),t._v("\nThis "),e("code",[t._v("GraphQL[R]")]),t._v(" instance need to be "),e("code",[t._v("public")]),t._v(". If it's "),e("code",[t._v("private")]),t._v(" or "),e("code",[t._v("protected")]),t._v(", the plugin code generator will not have access to it and will fail.")]),t._v(" "),e("p",[t._v("Let's say you have an object "),e("code",[t._v("CalibanServer")]),t._v(" object in your "),e("code",[t._v("api")]),t._v(" sbt module:")]),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 keyword"}},[t._v("package")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("com"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("example"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("my"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("awesome"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("project"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("api")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("GraphQL"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("graphQL\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("GraphQL\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" CalibanServer "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n \n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" graphqlApi"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Resolvers"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("resolver"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n \n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("You'll need to add in your sbt definition:")]),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 keyword"}},[t._v("lazy")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n project\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("enablePlugins"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CompileTimeCalibanServerPlugin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("settings"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Compile "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" ctCalibanServer "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" ctCalibanServerSettings "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Seq"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.example.my.awesome.project.api.CalibanServer.graphqlApi"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" ClientGenerationSettings"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("default\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v('This is the minimal working configuration for the "server side".')]),t._v(" "),e("p",[t._v("Now, you may want to tweak how the client code is generated."),e("br"),t._v("\nFor that, you'll have to replace the "),e("code",[t._v("ClientGenerationSettings.default")]),t._v(" with the configuration that suits you the best."),e("br"),t._v("\nThis "),e("code",[t._v("ClientGenerationSettings")]),t._v(" case class gives you the following configuration options:")]),t._v(" "),e("ul",[e("li",[e("code",[t._v("packageName: String")]),t._v(": The package in which the code will be generated (default: "),e("code",[t._v("generated")]),t._v(").")]),t._v(" "),e("li",[e("code",[t._v("clientName: String")]),t._v(": The name of the client class generated (default: "),e("code",[t._v("Client")]),t._v(").")]),t._v(" "),e("li",[e("code",[t._v("scalafmtPath: Option[String]")]),t._v(": Path to a scalafmt config (default: "),e("code",[t._v(".scalafmt.conf")]),t._v(")")]),t._v(" "),e("li",[e("code",[t._v("genView: Boolean")]),t._v(": Provide a case class and helper method to select all fields on an object (default: "),e("code",[t._v("false")]),t._v(")")]),t._v(" "),e("li",[e("code",[t._v("scalarMappings: : List[(String, String)]")]),t._v(": A mapping from GraphQL scalar types to JVM types, as unknown scalar types are represented as "),e("code",[t._v("String")]),t._v(" by default.")]),t._v(" "),e("li",[e("code",[t._v("imports: List[String]")]),t._v(": A list of imports to be added to the top of a generated client.")]),t._v(" "),e("li",[e("code",[t._v("splitFiles: Boolean")]),t._v(": Split single client object into multiple files (default: "),e("code",[t._v("false")]),t._v(")")]),t._v(" "),e("li",[e("code",[t._v("enableFmt: Boolean")]),t._v(": Enable code formatting with scalafmt (default: "),e("code",[t._v("true")]),t._v(")")]),t._v(" "),e("li",[e("code",[t._v("extensibleEnums: Boolean")]),t._v(": Generate a fallback case class for unknown enum values (default: "),e("code",[t._v("false")]),t._v(")")])]),t._v(" "),e("p",[t._v("Let's take a example:")]),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 keyword"}},[t._v("lazy")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n project\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("enablePlugins"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CompileTimeCalibanServerPlugin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("settings"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Compile "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" ctCalibanServer "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" ctCalibanServerSettings "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Seq"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.example.my.awesome.project.api.CalibanServer.graphqlApi"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v("\n ClientGenerationSettings"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n packageName "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.example.my.awesome.project.client.generated"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n clientName "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"CalibanClient"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n splitFiles "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v('That\'s all. You now know how to configure the "server side" of this plugin.'),e("br"),t._v('\nLet\'s now see how to configure the "client side".')]),t._v(" "),e("h4",{attrs:{id:"configure-the-client-side"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#configure-the-client-side"}},[t._v("#")]),t._v(" Configure the client side")]),t._v(" "),e("p",[t._v('The "client side" of this plugin is here to help you define where your Caliban client code is generated.')]),t._v(" "),e("p",[t._v("The first thing to do is to activate the "),e("code",[t._v("CompileTimeCalibanClientPlugin")]),t._v(" in the sbt module where you want your Caliban client code to be generated into.")]),t._v(" "),e("p",[t._v("Let's say you have a "),e("code",[t._v("client")]),t._v(" sbt module defined in your "),e("code",[t._v("build.sbt")]),t._v(":")]),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 keyword"}},[t._v("lazy")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" client "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n project\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("enablePlugins"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CompileTimeCalibanClientPlugin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("You only have one thing left to do."),e("br"),t._v('\nYou need to reference your "server side" sbt module (here '),e("code",[t._v("api")]),t._v(') in your "client side" sbt module (here '),e("code",[t._v("client")]),t._v(") definition so the plugin knows that you want to generate the Caliban client code for your "),e("code",[t._v("api")]),t._v(" server\nin this "),e("code",[t._v("client")]),t._v(" sbt module:")]),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 keyword"}},[t._v("lazy")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" client "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n project\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("enablePlugins"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CompileTimeCalibanClientPlugin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("settings"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Compile "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" ctCalibanClient "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" ctCalibanClientsSettings "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Seq"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("api"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v('This is the minimal working configuration for the "client side".')]),t._v(" "),e("p",[t._v("By default, the Caliban client code will be generated in your "),e("code",[t._v("src/main/scala")]),t._v(" directory of your "),e("code",[t._v("client")]),t._v(" sbt module."),e("br"),t._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 "),e("code",[t._v("target")]),t._v(" directory instead:")]),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 keyword"}},[t._v("lazy")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" client "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n project\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("enablePlugins"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CompileTimeCalibanClientPlugin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("settings"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Compile "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" ctCalibanClient "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" ctCalibanClientsSettings "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Seq"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("api"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Compile "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" ctCalibanClient "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" ctCalibanClientsVersionedCode "),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 boolean"}},[t._v("false")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// By default, it's true.")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("You're done. πŸŽ‰"),e("br"),t._v("\nYou can now reload your sbt config and recompile your project. Your Caliban client code will be generated during the compilation process.")]),t._v(" "),e("h4",{attrs:{id:"additional-information-about-compiletimecalibanplugin"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#additional-information-about-compiletimecalibanplugin"}},[t._v("#")]),t._v(" Additional information about CompileTimeCalibanPlugin")]),t._v(" "),e("p",[t._v("As you may have seen in the "),e("a",{attrs:{href:"https://github.com/guizmaii/poc_compile_time_caliban_client_generation",target:"_blank",rel:"noopener noreferrer"}},[t._v("demo project"),e("OutboundLink")],1),t._v(", you can have more complex configurations for this plugin."),e("br"),t._v("\nYou can have more than one "),e("code",[t._v("GraphQL[R]")]),t._v(" instance per server. Each "),e("code",[t._v("GraphQL[R]")]),t._v(" instance can have its own client code generation configuration."),e("br"),t._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.')]),t._v(" "),e("h2",{attrs:{id:"query-building"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#query-building"}},[t._v("#")]),t._v(" Query building")]),t._v(" "),e("p",[t._v("Once the boilerplate code is generated, you can start building queries. For each "),e("em",[t._v("type")]),t._v(" in your schema, a corresponding Scala object has been created. For each "),e("em",[t._v("field")]),t._v(" in your schema, a corresponding Scala function has been created.")]),t._v(" "),e("p",[t._v("For example, given the following schema:")]),t._v(" "),e("div",{staticClass:"language-graphql extra-class"},[e("pre",{pre:!0,attrs:{class:"language-graphql"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("nicknames")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("origin")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("Your generated code will have the following:")]),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 keyword"}},[t._v("object")]),t._v(" Character "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" name"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" nicknames"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" origin"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("A "),e("code",[t._v("SelectionBuilder[Origin, A]")]),t._v(" is a selection from a parent type "),e("code",[t._v("Origin")]),t._v(" that returns a result of type "),e("code",[t._v("A")]),t._v(". In this example, "),e("code",[t._v("name")]),t._v(" is a selection from a "),e("code",[t._v("Character")]),t._v(" that returns a "),e("code",[t._v("String")]),t._v(".")]),t._v(" "),e("p",[t._v("You can combine multiple selections using the "),e("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(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" selection"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nicknames\n")])])]),e("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 "),e("code",[t._v("mapN")]),t._v(" to map a nested tuple to a case class.")]),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 keyword"}},[t._v("case")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" nickname"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" origin"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" character"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nicknames "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mapN"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("Fields that return an object type will require an inner selection, which is another "),e("code",[t._v("SelectionBuilder")]),t._v(". Let's consider the following "),e("code",[t._v("Query")]),t._v(" type.")]),t._v(" "),e("div",{staticClass:"language-graphql extra-class"},[e("pre",{pre:!0,attrs:{class:"language-graphql"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Query")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("characters")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("When calling "),e("code",[t._v("characters")]),t._v(", we need to provide a "),e("code",[t._v("SelectionBuilder[Character, ?]")]),t._v(" to indicate which fields to select on the returned "),e("code",[t._v("Character")]),t._v(".")]),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 keyword"}},[t._v("val")]),t._v(" query"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("RootQuery"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Query"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characters "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nicknames "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mapN"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("Or if we reuse the "),e("code",[t._v("character")]),t._v(" selection we just created:")]),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 keyword"}},[t._v("val")]),t._v(" query"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("RootQuery"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Query"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characters "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n character\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("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(" "),e("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(" "),e("div",{staticClass:"language-graphql extra-class"},[e("pre",{pre:!0,attrs:{class:"language-graphql"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Query")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("characters")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("origin")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("You now need to provide an "),e("code",[t._v("Origin")]),t._v(" when calling "),e("code",[t._v("characters")]),t._v(":")]),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 keyword"}},[t._v("val")]),t._v(" query"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("RootQuery"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Query"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("MARS"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n character\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("h2",{attrs:{id:"automated-generation-of-a-view-projection"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#automated-generation-of-a-view-projection"}},[t._v("#")]),t._v(" Automated generation of a view projection")]),t._v(" "),e("p",[e("code",[t._v("ClientWriter")]),t._v(" can generate a view projection for a GraphQL type.")]),t._v(" "),e("p",[t._v("For example, given the following schema:")]),t._v(" "),e("div",{staticClass:"language-graphql extra-class"},[e("pre",{pre:!0,attrs:{class:"language-graphql"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("description")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("details")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),t._v(" \n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("nicknames")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("origin")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("filter")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("Your generated code will have the following:")]),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 keyword"}},[t._v("type")]),t._v(" Origin\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Origin "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" OriginView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("description"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" details"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" ViewSelection "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" OriginView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" view"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ViewSelection "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("description "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" details"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("description"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" details"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n OriginView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("description"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" details"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" description"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Option"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Field"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"description"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" OptionOf"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Scalar"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" details"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Option"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Field"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"details"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" OptionOf"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Scalar"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Character\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Character "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("OriginSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" nicknames"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" origin"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" OriginSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" ViewSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("OriginSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("OriginSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" view"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("OriginSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("originFilter"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" None"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n originSelection"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" OriginSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ViewSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("OriginSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" nicknames "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("originFilter"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("originSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" nicknames"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" nicknames"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" name"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Field"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Scalar"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" nicknames"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Field"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"nicknames"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ListOf"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Scalar"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("A"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n filter"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" None\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("innerSelection"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Field"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"origin"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Obj"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("innerSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" arguments "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Argument"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"filter"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" filter"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("Then you can build a query the way you want:")]),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 keyword"}},[t._v("val")]),t._v(" characterWithOriginAllFields"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("View"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("view"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("None"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("view"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" characterWithOriginOnlyDetails"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("view"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Some"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"some filter"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("details"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h2",{attrs:{id:"supporting-enums-evolution"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#supporting-enums-evolution"}},[t._v("#")]),t._v(" Supporting enums evolution")]),t._v(" "),e("p",[t._v("In GraphQL, adding new values to Enums is not considered a breaking change. If you want your generated client to accept enum values introduced after the code is generated, you can configure the "),e("code",[t._v("ClientWriter")]),t._v(" to generate a fallback "),e("code",[t._v("case class __Unknown(value: string)")]),t._v(".")]),t._v(" "),e("h2",{attrs:{id:"request-execution"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#request-execution"}},[t._v("#")]),t._v(" Request execution")]),t._v(" "),e("p",[t._v("Once your query or mutation is created, it is time to execute it. To do that, you can transform your "),e("code",[t._v("SelectionBuilder")]),t._v(" into an "),e("code",[t._v("sttp")]),t._v(" request by calling "),e("code",[t._v(".toRequest")]),t._v(".")]),t._v(" "),e("p",[t._v("This function takes the URL of your GraphQL server and some options:")]),t._v(" "),e("ul",[e("li",[t._v("a boolean "),e("code",[t._v("useVariables")]),t._v(" that determines if arguments should be using variables or not (default: false)")]),t._v(" "),e("li",[t._v("an optional string "),e("code",[t._v("queryName")]),t._v(" if you want to name your query (default: no name)")]),t._v(" "),e("li",[t._v("a boolean "),e("code",[t._v("dropNullInputValues")]),t._v(" that determines if null fields from input objects should be dropped (default: false)")])]),t._v(" "),e("p",[t._v("You can then simply run the "),e("code",[t._v("sttp")]),t._v(" request with the backend of your choice. See the "),e("a",{attrs:{href:"https://sttp.readthedocs.io/en/latest/",target:"_blank",rel:"noopener noreferrer"}},[t._v("sttp docs"),e("OutboundLink")],1),t._v(" if you are not familiar with it.")]),t._v(" "),e("p",[t._v("Here is an example using the "),e("code",[t._v("AsyncHttpClient")]),t._v(" backend for "),e("code",[t._v("ZIO")]),t._v(":")]),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 keyword"}},[t._v("import")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("client"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("client"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("asynchttpclient"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("zio"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("AsyncHttpClientZioBackend\n\nAsyncHttpClientZioBackend"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("flatMap "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" backend "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" serverUrl "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" uri"),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://localhost:8088/api/graphql"')]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" result"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Task"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n query"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toRequest"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("serverUrl"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("send"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("body"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("absolve\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("As a result, we get a ZIO "),e("code",[t._v("Task")]),t._v(" whose return type is the same as our "),e("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(" "),e("p",[t._v("The "),e("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/",target:"_blank",rel:"noopener noreferrer"}},[t._v("examples"),e("OutboundLink")],1),t._v(" project contains a runnable sample code that queries the example GraphQL backend.")]),t._v(" "),e("div",{staticClass:"custom-block warning"},[e("p",{staticClass:"custom-block-title"},[t._v("Limitations")]),t._v(" "),e("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(" "),e("p",[t._v("Type extensions are not supported by the codegen tool.")])]),t._v(" "),e("h2",{attrs:{id:"laminext-integration"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#laminext-integration"}},[t._v("#")]),t._v(" Laminext Integration")]),t._v(" "),e("p",[t._v("If you are using the Scala.js framework "),e("a",{attrs:{href:"https://laminar.dev",target:"_blank",rel:"noopener noreferrer"}},[t._v("Laminar"),e("OutboundLink")],1),t._v(", there is a module that makes the integration even nicer, with support for subscriptions.\nIt is depending on "),e("a",{attrs:{href:"https://laminext.dev",target:"_blank",rel:"noopener noreferrer"}},[t._v("Laminext"),e("OutboundLink")],1),t._v(", a library that provides nice little helpers for Laminar, in particular for using "),e("code",[t._v("Fetch")]),t._v(" and "),e("code",[t._v("WebSocket")]),t._v(".")]),t._v(" "),e("p",[t._v("To use it, import the "),e("code",[t._v("caliban-client-laminext")]),t._v(" module:")]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v('libraryDependencies += "com.github.ghostdogpr" %%% "caliban-client-laminext" % "1.2.1"\n')])])]),e("p",[t._v("Add the following import to your code:")]),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 keyword"}},[t._v("import")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("client"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("laminext"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n")])])]),e("p",[t._v("This import adds an extension method "),e("code",[t._v("toEventStream(uri)")]),t._v(" to "),e("code",[t._v("SelectionBuilder")]),t._v(", which is similar to "),e("code",[t._v("toRequest")]),t._v(" except it creates an "),e("code",[t._v("EventStream")]),t._v(" instead of an sttp "),e("code",[t._v("Request")]),t._v(".")]),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 keyword"}},[t._v("val")]),t._v(" characters"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Var"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Var"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Nil"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" uri "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://localhost:8088/api/graphql"')]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" getCharacters "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("None"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Client"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toEventStream"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("uri"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" view"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Div "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" \n div"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Characters: "')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n getCharacters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("collectRight "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" characters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("set _"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n child "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" characters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("signal"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" div"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mkString"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('", "')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("To use subscriptions, you first need to create a "),e("code",[t._v("WebSocket")]),t._v(" with protocol "),e("code",[t._v("graphql-ws")]),t._v(". Use the extension method "),e("code",[t._v(".graphql")]),t._v(" instead of "),e("code",[t._v(".text")]),t._v(" or "),e("code",[t._v(".json")]),t._v(".\nThen use the extension method "),e("code",[t._v("toSubscription")]),t._v(" on your "),e("code",[t._v("SelectionBuilder")]),t._v(" and pass the "),e("code",[t._v("WebSocket")]),t._v(" object.")]),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 keyword"}},[t._v("val")]),t._v(" ws "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" WebSocket"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("url"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ws://localhost:8088/ws/graphql"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"graphql-ws"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("graphql"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("build"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" deletedCharacters "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Subscriptions"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characterDeleted"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toSubscription"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ws"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("Finally, you can use "),e("code",[t._v("ws.connect")]),t._v(" to connect the "),e("code",[t._v("WebSocket")]),t._v(", "),e("code",[t._v("ws.init()")]),t._v(" to initialize the communication with the graphql server and "),e("code",[t._v(".received")]),t._v(" to get an "),e("code",[t._v("EventStream")]),t._v(" of the type returned by your subscription.")]),t._v(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[t._v("ws"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("connect"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\nws"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("connected "),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 punctuation"}},[t._v("(")]),t._v("_ "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ws"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("init"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\ndeletedCharacters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("received"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("collectRight "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" \n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" characters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("update"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("filterNot"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_ "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" name"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n")])])]),e("p",[t._v("There is a full example in the "),e("code",[t._v("test")]),t._v(" folder of the "),e("code",[t._v("caliban-client-laminext")]),t._v(" module.\nTo use it:")]),t._v(" "),e("ul",[e("li",[t._v("run "),e("code",[t._v("ExampleApp")]),t._v(" of the http4s server example (it supports CORS)")]),t._v(" "),e("li",[t._v("run "),e("code",[t._v("clientLaminextJS/Test/fastLinkJS")]),t._v(" to compile the Scala.js code")]),t._v(" "),e("li",[t._v("run "),e("code",[t._v("yarn install")]),t._v(" and "),e("code",[t._v("yarn exec vite")]),t._v(" in the "),e("code",[t._v("caliban-client-laminext")]),t._v(" folder")]),t._v(" "),e("li",[t._v("the example page will be running on "),e("a",{attrs:{href:"http://localhost:3000",target:"_blank",rel:"noopener noreferrer"}},[t._v("http://localhost:3000"),e("OutboundLink")],1)])])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[10],{395:function(t,a,e){"use strict";e.r(a);var s=e(54),n=Object(s.a)({},(function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"graphql-client"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#graphql-client"}},[t._v("#")]),t._v(" GraphQL Client")]),t._v(" "),e("p",[e("strong",[t._v("Caliban-client")]),t._v(" is a module independent from Caliban that makes it possible to write GraphQL queries using Scala code in a type-safe and functional fashion. It is built on top of "),e("a",{attrs:{href:"https://github.com/softwaremill/sttp",target:"_blank",rel:"noopener noreferrer"}},[t._v("sttp"),e("OutboundLink")],1),t._v(", which means you can run requests using the backend of your choice.")]),t._v(" "),e("p",[t._v("Just like Caliban, "),e("code",[t._v("caliban-client")]),t._v(" offers a purely functional interface and keeps the boilerplate minimal. It works as follows:")]),t._v(" "),e("ol",[e("li",[t._v("Use the "),e("code",[t._v("caliban-codegen-sbt")]),t._v(" tool to generate boilerplate code from a given GraphQL schema")]),t._v(" "),e("li",[t._v("Write your GraphQL query/mutation by combining helpers from the generated code")]),t._v(" "),e("li",[t._v("Transform your query/mutation into an "),e("code",[t._v("sttp")]),t._v(" request and run it with your preferred backend")])]),t._v(" "),e("h2",{attrs:{id:"dependencies"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#dependencies"}},[t._v("#")]),t._v(" Dependencies")]),t._v(" "),e("p",[t._v("To use "),e("code",[t._v("caliban-client")]),t._v(", add the following line in your "),e("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v('libraryDependencies += "com.github.ghostdogpr" %% "caliban-client" % "1.2.1"\n')])])]),e("p",[t._v("Caliban-client is available for ScalaJS. To use it in a ScalaJS project, instead add this line to your "),e("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v('libraryDependencies += "com.github.ghostdogpr" %%% "caliban-client" % "1.2.1"\n')])])]),e("h2",{attrs:{id:"code-generation"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#code-generation"}},[t._v("#")]),t._v(" Code generation")]),t._v(" "),e("p",[t._v("Caliban provides two sbt plugins to generate your client(s) code.")]),t._v(" "),e("p",[t._v("The first one, named "),e("code",[t._v("CalibanPlugin")]),t._v(", allows you to generate the client code from a schema file or from a server URL.")]),t._v(" "),e("p",[t._v("The second one, named "),e("code",[t._v("CompileTimeCalibanPlugin")]),t._v(", allows you to generate the client code from your server code."),e("br"),t._v('\nThis second "meta" plugin is actually made of two "concrete" plugins, '),e("code",[t._v("CompileTimeCalibanServerPlugin")]),t._v(" and "),e("code",[t._v("CompileTimeCalibanClientPlugin")]),t._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.")]),t._v(" "),e("p",[t._v("To use any of these two plugins, you'll first need to add following dependency to your "),e("code",[t._v("project/plugins.sbt")]),t._v(" file:")]),t._v(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[t._v("addSbtPlugin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),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("%")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-codegen-sbt"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1.2.1"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h3",{attrs:{id:"calibanplugin"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#calibanplugin"}},[t._v("#")]),t._v(" CalibanPlugin")]),t._v(" "),e("p",[t._v("The first step for building GraphQL queries with "),e("code",[t._v("caliban-client")]),t._v(" is to generate boilerplate code from a GraphQL schema. For that, you need a file containing your schema (if your backend uses "),e("code",[t._v("caliban")]),t._v(", you can get it by calling "),e("code",[t._v("GraphQL#render")]),t._v(" on your API).")]),t._v(" "),e("p",[t._v("And enable it in your "),e("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[t._v("enablePlugins"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CalibanPlugin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h4",{attrs:{id:"from-a-schema-file"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#from-a-schema-file"}},[t._v("#")]),t._v(" From a schema file")]),t._v(" "),e("p",[t._v("At this point, the "),e("code",[t._v("caliban")]),t._v(" command will cause any files in "),e("code",[t._v("src/main/graphql")]),t._v(" to be translated into a Caliban-generated client library. This happens automatically any time you "),e("code",[t._v("compile")]),t._v(".")]),t._v(" "),e("p",[t._v("By default, all clients are generated with the same client name as the source file, in the "),e("code",[t._v("caliban")]),t._v(" top-level package.")]),t._v(" "),e("p",[t._v("In order to supply more configuration options to the code generator, you can use the "),e("code",[t._v("calibanSettings")]),t._v(" sbt setting, combined with the "),e("code",[t._v("calibanSetting")]),t._v(" function to scope the settings to a particular file:")]),t._v(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// The `file("Service.graphql")` is a path suffix for some file in `src/main/graphql`')]),t._v("\n Compile "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" caliban "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" calibanSettings "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" calibanSetting"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("file"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Service.graphql"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n cs "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n cs"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("packageName"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.example.graphql.client"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("scalarMapping"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"LanguageCode"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.example.models.LanguageCode"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("scalarMapping"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Timestamp"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"java.sql.Timestamp"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"DayOfWeek"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"java.time.DayOfWeek"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"IntRange"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.tminglei.slickpg.Range[Int]"')]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("imports"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.example.graphql.client.implicits._"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h4",{attrs:{id:"from-a-server-url"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#from-a-server-url"}},[t._v("#")]),t._v(" From a server URL")]),t._v(" "),e("p",[t._v("The "),e("code",[t._v("calibanSetting")]),t._v(" function also permits generating clients for supplied "),e("code",[t._v("url")]),t._v("'s:")]),t._v(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[t._v(" Compile "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" caliban "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" calibanSettings "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" calibanSetting"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("url"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://my-example-service/graphql"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n cs "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n cs"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("clientName"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ExampleServiceClient"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("packageName"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.example.graphql.client"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h4",{attrs:{id:"calibansetting-config-parameters"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#calibansetting-config-parameters"}},[t._v("#")]),t._v(" "),e("code",[t._v("calibanSetting")]),t._v(" config parameters")]),t._v(" "),e("p",[t._v("The settings available on the "),e("code",[t._v("cs")]),t._v(" ("),e("code",[t._v("CalibanSettings")]),t._v(") builder are:")]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v(" def scalafmtPath(path: String): CalibanSettings // Path to a scalafmt config (default: .scalafmt.conf)\n def packageName(name: String): CalibanSettings // Which package to put the generated clients in (default: caliban)\n def genView(value: Boolean): CalibanSettings // Provide a case class and helper method to select all fields on an object (default: false)\n def scalarMapping(mapping: (String,String)*): CalibanSettings // A mapping from GraphQL scalar types to JVM types, as unknown scalar types are represented as String by default.\n def imports(values: String*): CalibanSettings // A list of imports to be added to the top of a generated client\n def splitFiles(value: Boolean): CalibanSettings // Split single client object into multiple files (default: false)\n def enableFmt(value: Boolean): CalibanSettings // Enable code formatting with scalafmt (default: true)\n def extensibleEnums(value: Boolean): CalibanSettings // Generate a fallback case class for unknown enum values (default: false)\n\n // Only defined for `url` settings, for use in supplying extra headers when fetching the schema itself\n def headers(pairs: (String,String)*): CalibanSettings\n")])])]),e("h4",{attrs:{id:"calibangenclient"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#calibangenclient"}},[t._v("#")]),t._v(" "),e("code",[t._v("calibanGenClient")])]),t._v(" "),e("p",[t._v("If you prefer to generate the client explicitly rather than automatically, you can use "),e("code",[t._v("calibanGenClient")]),t._v(" on the SBT CLI as follows:")]),t._v(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[t._v("calibanGenClient schemaPath outputPath "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("scalafmtPath path"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("headers name"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("value"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("name2"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("value2"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("genView "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("scalarMappings gqlType"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("f"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("q"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("d"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Type"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("gqlType2"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("f"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("q"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("d"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Type2"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("imports a"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("b"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("c"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("c"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("d"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("E"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("splitFiles "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("enableFmt "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\ncalibanGenClient project"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("schema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("graphql src"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("main"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("client"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("Client"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("scala "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("genView "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v(" \n")])])]),e("p",[t._v("This command will generate a Scala file in "),e("code",[t._v("outputPath")]),t._v(" containing helper functions for all the types defined in the provided GraphQL schema defined at "),e("code",[t._v("schemaPath")]),t._v(".\nIf you need to disable generating clients from "),e("code",[t._v("src/main/graphql")]),t._v(", please include "),e("code",[t._v("Compile / caliban / calibanGenerator := Seq.empty")]),t._v(" in your project settings.\nInstead of a file, you can provide a URL and the schema will be obtained using introspection.\nThe generated code will be formatted with Scalafmt using the configuration defined by "),e("code",[t._v("--scalafmtPath")]),t._v(" option (default: "),e("code",[t._v(".scalafmt.conf")]),t._v(").\nIf you provide a URL for "),e("code",[t._v("schemaPath")]),t._v(", you can provide request headers with "),e("code",[t._v("--headers")]),t._v(" option.\nThe package of the generated code is derived from the folder of "),e("code",[t._v("outputPath")]),t._v(".\nThis can be overridden by providing an alternative package with the "),e("code",[t._v("--packageName")]),t._v("\noption.\nThe generated object name is derived from "),e("code",[t._v("outputPath")]),t._v(" file name but can be overridden with the "),e("code",[t._v("--clientName")]),t._v(" option.\nProvide "),e("code",[t._v("--genView true")]),t._v(" option if you want to generate a view for the GraphQL types.\nIf you want to force a mapping between a GraphQL type and a Scala class (such as scalars), you can use the\n"),e("code",[t._v("--scalarMappings")]),t._v(" option. Also you can add imports for example for your ArgEncoder implicits by providing "),e("code",[t._v("--imports")]),t._v(" option.\nUse the "),e("code",[t._v("--splitFiles true")]),t._v(" option if you want to generate multiple files within the same package instead of a single file.\nIn this case the filename part of the "),e("code",[t._v("outputPath")]),t._v(" will be ignored, but the value will still be used to determine the mandatory package name and the destination directory.\nThis can be helpful with large GraphQL schemas and incremental compilation.\nProvide "),e("code",[t._v("--enableFmt false")]),t._v(" option if you don't need to format generated files.\nProvide "),e("code",[t._v("--extensibleEnums true")]),t._v(" option if you want to generate a fallback case class for unknown enum values.")]),t._v(" "),e("h3",{attrs:{id:"compiletimecalibanplugin"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#compiletimecalibanplugin"}},[t._v("#")]),t._v(" CompileTimeCalibanPlugin")]),t._v(" "),e("p",[t._v("As mentioned in the introduction of the "),e("a",{attrs:{href:"#code-generation"}},[t._v("Code Generation")]),t._v(' chapter, this "meta" plugin is actually made of two "concrete" sbt plugins, '),e("code",[t._v("CompileTimeCalibanServerPlugin")]),t._v(" and "),e("code",[t._v("CompileTimeCalibanClientPlugin")]),t._v(",\nthat you'll both need to configure in your project be able to generate your Caliban client code from your Caliban server code..")]),t._v(" "),e("p",[t._v("You can find a demo project using this plugin here: "),e("a",{attrs:{href:"https://github.com/guizmaii/poc_compile_time_caliban_client_generation",target:"_blank",rel:"noopener noreferrer"}},[t._v("Demo project"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("To generate the Caliban client code from you Caliban server code, you need to do two things:")]),t._v(" "),e("ol",[e("li",[e("p",[t._v("Tell to the plugin where your Caliban "),e("code",[t._v("GraphQL[R]")]),t._v(" instances for which you want to generate a client are and configure the client code generator."),e("br"),t._v("\nHow to configure this is explained in the following "),e("a",{attrs:{href:"#configure-the-server-side"}},[t._v("Configure the server side")]),t._v(" chapter.")])]),t._v(" "),e("li",[e("p",[t._v("Tell to the plugin where you want to generate your client(s)."),e("br"),t._v("\nHow to configure this is explained in the following "),e("a",{attrs:{href:"#configure-the-client-side"}},[t._v("Configure the client side")]),t._v(" chapter.")])])]),t._v(" "),e("h4",{attrs:{id:"configure-the-server-side"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#configure-the-server-side"}},[t._v("#")]),t._v(" Configure the server side")]),t._v(" "),e("p",[t._v("First, you'll need to activate the "),e("code",[t._v("CompileTimeCalibanServerPlugin")]),t._v(" plugin in all the sbt modules of your project containing a "),e("code",[t._v("GraphQL[R]")]),t._v(" instance for which you want to generate a client.")]),t._v(" "),e("p",[t._v("Let's say you have an "),e("code",[t._v("api")]),t._v(" sbt module defined in your "),e("code",[t._v("build.sbt")]),t._v(" which contains your Caliban server code:")]),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 keyword"}},[t._v("lazy")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n project\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("enablePlugins"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CompileTimeCalibanServerPlugin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v('Now, you need to tell to the "server side" plugin where is your '),e("code",[t._v("GraphQL[R]")]),t._v(" instance for which you want to generate a client."),e("br"),t._v("\nThis "),e("code",[t._v("GraphQL[R]")]),t._v(" instance need to be "),e("code",[t._v("public")]),t._v(". If it's "),e("code",[t._v("private")]),t._v(" or "),e("code",[t._v("protected")]),t._v(", the plugin code generator will not have access to it and will fail.")]),t._v(" "),e("p",[t._v("Let's say you have an object "),e("code",[t._v("CalibanServer")]),t._v(" object in your "),e("code",[t._v("api")]),t._v(" sbt module:")]),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 keyword"}},[t._v("package")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("com"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("example"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("my"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("awesome"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("project"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("api")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("GraphQL"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("graphQL\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("GraphQL\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" CalibanServer "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n \n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" graphqlApi"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Resolvers"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("resolver"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n \n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("You'll need to add in your sbt definition:")]),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 keyword"}},[t._v("lazy")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n project\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("enablePlugins"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CompileTimeCalibanServerPlugin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("settings"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Compile "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" ctCalibanServer "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" ctCalibanServerSettings "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Seq"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.example.my.awesome.project.api.CalibanServer.graphqlApi"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" ClientGenerationSettings"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("default\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v('This is the minimal working configuration for the "server side".')]),t._v(" "),e("p",[t._v("Now, you may want to tweak how the client code is generated."),e("br"),t._v("\nFor that, you'll have to replace the "),e("code",[t._v("ClientGenerationSettings.default")]),t._v(" with the configuration that suits you the best."),e("br"),t._v("\nThis "),e("code",[t._v("ClientGenerationSettings")]),t._v(" case class gives you the following configuration options:")]),t._v(" "),e("ul",[e("li",[e("code",[t._v("packageName: String")]),t._v(": The package in which the code will be generated (default: "),e("code",[t._v("generated")]),t._v(").")]),t._v(" "),e("li",[e("code",[t._v("clientName: String")]),t._v(": The name of the client class generated (default: "),e("code",[t._v("Client")]),t._v(").")]),t._v(" "),e("li",[e("code",[t._v("scalafmtPath: Option[String]")]),t._v(": Path to a scalafmt config (default: "),e("code",[t._v(".scalafmt.conf")]),t._v(")")]),t._v(" "),e("li",[e("code",[t._v("genView: Boolean")]),t._v(": Provide a case class and helper method to select all fields on an object (default: "),e("code",[t._v("false")]),t._v(")")]),t._v(" "),e("li",[e("code",[t._v("scalarMappings: : List[(String, String)]")]),t._v(": A mapping from GraphQL scalar types to JVM types, as unknown scalar types are represented as "),e("code",[t._v("String")]),t._v(" by default.")]),t._v(" "),e("li",[e("code",[t._v("imports: List[String]")]),t._v(": A list of imports to be added to the top of a generated client.")]),t._v(" "),e("li",[e("code",[t._v("splitFiles: Boolean")]),t._v(": Split single client object into multiple files (default: "),e("code",[t._v("false")]),t._v(")")]),t._v(" "),e("li",[e("code",[t._v("enableFmt: Boolean")]),t._v(": Enable code formatting with scalafmt (default: "),e("code",[t._v("true")]),t._v(")")]),t._v(" "),e("li",[e("code",[t._v("extensibleEnums: Boolean")]),t._v(": Generate a fallback case class for unknown enum values (default: "),e("code",[t._v("false")]),t._v(")")])]),t._v(" "),e("p",[t._v("Let's take a example:")]),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 keyword"}},[t._v("lazy")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n project\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("enablePlugins"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CompileTimeCalibanServerPlugin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("settings"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Compile "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" ctCalibanServer "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" ctCalibanServerSettings "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Seq"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.example.my.awesome.project.api.CalibanServer.graphqlApi"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v("\n ClientGenerationSettings"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n packageName "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.example.my.awesome.project.client.generated"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n clientName "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"CalibanClient"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n splitFiles "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v('That\'s all. You now know how to configure the "server side" of this plugin.'),e("br"),t._v('\nLet\'s now see how to configure the "client side".')]),t._v(" "),e("h4",{attrs:{id:"configure-the-client-side"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#configure-the-client-side"}},[t._v("#")]),t._v(" Configure the client side")]),t._v(" "),e("p",[t._v('The "client side" of this plugin is here to help you define where your Caliban client code is generated.')]),t._v(" "),e("p",[t._v("The first thing to do is to activate the "),e("code",[t._v("CompileTimeCalibanClientPlugin")]),t._v(" in the sbt module where you want your Caliban client code to be generated into.")]),t._v(" "),e("p",[t._v("Let's say you have a "),e("code",[t._v("client")]),t._v(" sbt module defined in your "),e("code",[t._v("build.sbt")]),t._v(":")]),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 keyword"}},[t._v("lazy")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" client "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n project\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("enablePlugins"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CompileTimeCalibanClientPlugin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("You only have one thing left to do."),e("br"),t._v('\nYou need to reference your "server side" sbt module (here '),e("code",[t._v("api")]),t._v(') in your "client side" sbt module (here '),e("code",[t._v("client")]),t._v(") definition so the plugin knows that you want to generate the Caliban client code for your "),e("code",[t._v("api")]),t._v(" server\nin this "),e("code",[t._v("client")]),t._v(" sbt module:")]),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 keyword"}},[t._v("lazy")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" client "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n project\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("enablePlugins"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CompileTimeCalibanClientPlugin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("settings"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Compile "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" ctCalibanClient "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" ctCalibanClientsSettings "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Seq"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("api"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v('This is the minimal working configuration for the "client side".')]),t._v(" "),e("p",[t._v("By default, the Caliban client code will be generated in your "),e("code",[t._v("src/main/scala")]),t._v(" directory of your "),e("code",[t._v("client")]),t._v(" sbt module."),e("br"),t._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 "),e("code",[t._v("target")]),t._v(" directory instead:")]),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 keyword"}},[t._v("lazy")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" client "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n project\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("enablePlugins"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CompileTimeCalibanClientPlugin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("settings"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Compile "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" ctCalibanClient "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" ctCalibanClientsSettings "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Seq"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("api"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Compile "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" ctCalibanClient "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" ctCalibanClientsVersionedCode "),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 boolean"}},[t._v("false")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// By default, it's true.")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("You're done. πŸŽ‰"),e("br"),t._v("\nYou can now reload your sbt config and recompile your project. Your Caliban client code will be generated during the compilation process.")]),t._v(" "),e("h4",{attrs:{id:"additional-information-about-compiletimecalibanplugin"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#additional-information-about-compiletimecalibanplugin"}},[t._v("#")]),t._v(" Additional information about CompileTimeCalibanPlugin")]),t._v(" "),e("p",[t._v("As you may have seen in the "),e("a",{attrs:{href:"https://github.com/guizmaii/poc_compile_time_caliban_client_generation",target:"_blank",rel:"noopener noreferrer"}},[t._v("demo project"),e("OutboundLink")],1),t._v(", you can have more complex configurations for this plugin."),e("br"),t._v("\nYou can have more than one "),e("code",[t._v("GraphQL[R]")]),t._v(" instance per server. Each "),e("code",[t._v("GraphQL[R]")]),t._v(" instance can have its own client code generation configuration."),e("br"),t._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.')]),t._v(" "),e("h2",{attrs:{id:"query-building"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#query-building"}},[t._v("#")]),t._v(" Query building")]),t._v(" "),e("p",[t._v("Once the boilerplate code is generated, you can start building queries. For each "),e("em",[t._v("type")]),t._v(" in your schema, a corresponding Scala object has been created. For each "),e("em",[t._v("field")]),t._v(" in your schema, a corresponding Scala function has been created.")]),t._v(" "),e("p",[t._v("For example, given the following schema:")]),t._v(" "),e("div",{staticClass:"language-graphql extra-class"},[e("pre",{pre:!0,attrs:{class:"language-graphql"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("nicknames")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("origin")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("Your generated code will have the following:")]),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 keyword"}},[t._v("object")]),t._v(" Character "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" name"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" nicknames"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" origin"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("A "),e("code",[t._v("SelectionBuilder[Origin, A]")]),t._v(" is a selection from a parent type "),e("code",[t._v("Origin")]),t._v(" that returns a result of type "),e("code",[t._v("A")]),t._v(". In this example, "),e("code",[t._v("name")]),t._v(" is a selection from a "),e("code",[t._v("Character")]),t._v(" that returns a "),e("code",[t._v("String")]),t._v(".")]),t._v(" "),e("p",[t._v("You can combine multiple selections using the "),e("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(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" selection"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nicknames\n")])])]),e("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 "),e("code",[t._v("mapN")]),t._v(" to map a nested tuple to a case class.")]),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 keyword"}},[t._v("case")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" nickname"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" origin"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" character"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nicknames "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mapN"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("Fields that return an object type will require an inner selection, which is another "),e("code",[t._v("SelectionBuilder")]),t._v(". Let's consider the following "),e("code",[t._v("Query")]),t._v(" type.")]),t._v(" "),e("div",{staticClass:"language-graphql extra-class"},[e("pre",{pre:!0,attrs:{class:"language-graphql"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Query")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("characters")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("When calling "),e("code",[t._v("characters")]),t._v(", we need to provide a "),e("code",[t._v("SelectionBuilder[Character, ?]")]),t._v(" to indicate which fields to select on the returned "),e("code",[t._v("Character")]),t._v(".")]),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 keyword"}},[t._v("val")]),t._v(" query"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("RootQuery"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Query"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characters "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nicknames "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mapN"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("Or if we reuse the "),e("code",[t._v("character")]),t._v(" selection we just created:")]),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 keyword"}},[t._v("val")]),t._v(" query"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("RootQuery"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Query"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characters "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n character\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("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(" "),e("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(" "),e("div",{staticClass:"language-graphql extra-class"},[e("pre",{pre:!0,attrs:{class:"language-graphql"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Query")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("characters")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("origin")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("You now need to provide an "),e("code",[t._v("Origin")]),t._v(" when calling "),e("code",[t._v("characters")]),t._v(":")]),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 keyword"}},[t._v("val")]),t._v(" query"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("RootQuery"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Query"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("MARS"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n character\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("h2",{attrs:{id:"automated-generation-of-a-view-projection"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#automated-generation-of-a-view-projection"}},[t._v("#")]),t._v(" Automated generation of a view projection")]),t._v(" "),e("p",[e("code",[t._v("ClientWriter")]),t._v(" can generate a view projection for a GraphQL type.")]),t._v(" "),e("p",[t._v("For example, given the following schema:")]),t._v(" "),e("div",{staticClass:"language-graphql extra-class"},[e("pre",{pre:!0,attrs:{class:"language-graphql"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("description")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("details")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),t._v(" \n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("nicknames")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("origin")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("filter")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("Your generated code will have the following:")]),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 keyword"}},[t._v("type")]),t._v(" Origin\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Origin "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" OriginView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("description"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" details"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" ViewSelection "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" OriginView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" view"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ViewSelection "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("description "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" details"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("description"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" details"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n OriginView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("description"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" details"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" description"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Option"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Field"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"description"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" OptionOf"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Scalar"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" details"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Option"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Field"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"details"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" OptionOf"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Scalar"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Character\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Character "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("OriginSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" nicknames"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" origin"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" OriginSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" ViewSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("OriginSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("OriginSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" view"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("OriginSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("originFilter"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" None"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n originSelection"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" OriginSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ViewSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("OriginSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" nicknames "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("~")]),t._v(" origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("originFilter"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("originSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" nicknames"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" nicknames"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" name"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Field"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Scalar"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" nicknames"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Field"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"nicknames"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ListOf"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Scalar"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("A"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n filter"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" None\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("innerSelection"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Field"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"origin"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Obj"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("innerSelection"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" arguments "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Argument"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"filter"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" filter"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("Then you can build a query the way you want:")]),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 keyword"}},[t._v("val")]),t._v(" characterWithOriginAllFields"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("View"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("view"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("None"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("view"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" characterWithOriginOnlyDetails"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SelectionBuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("view"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Some"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"some filter"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Origin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("details"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h2",{attrs:{id:"supporting-enums-evolution"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#supporting-enums-evolution"}},[t._v("#")]),t._v(" Supporting enums evolution")]),t._v(" "),e("p",[t._v("In GraphQL, adding new values to Enums is not considered a breaking change. If you want your generated client to accept enum values introduced after the code is generated, you can configure the "),e("code",[t._v("ClientWriter")]),t._v(" to generate a fallback "),e("code",[t._v("case class __Unknown(value: string)")]),t._v(".")]),t._v(" "),e("h2",{attrs:{id:"request-execution"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#request-execution"}},[t._v("#")]),t._v(" Request execution")]),t._v(" "),e("p",[t._v("Once your query or mutation is created, it is time to execute it. To do that, you can transform your "),e("code",[t._v("SelectionBuilder")]),t._v(" into an "),e("code",[t._v("sttp")]),t._v(" request by calling "),e("code",[t._v(".toRequest")]),t._v(".")]),t._v(" "),e("p",[t._v("This function takes the URL of your GraphQL server and some options:")]),t._v(" "),e("ul",[e("li",[t._v("a boolean "),e("code",[t._v("useVariables")]),t._v(" that determines if arguments should be using variables or not (default: false)")]),t._v(" "),e("li",[t._v("an optional string "),e("code",[t._v("queryName")]),t._v(" if you want to name your query (default: no name)")]),t._v(" "),e("li",[t._v("a boolean "),e("code",[t._v("dropNullInputValues")]),t._v(" that determines if null fields from input objects should be dropped (default: false)")])]),t._v(" "),e("p",[t._v("You can then simply run the "),e("code",[t._v("sttp")]),t._v(" request with the backend of your choice. See the "),e("a",{attrs:{href:"https://sttp.readthedocs.io/en/latest/",target:"_blank",rel:"noopener noreferrer"}},[t._v("sttp docs"),e("OutboundLink")],1),t._v(" if you are not familiar with it.")]),t._v(" "),e("p",[t._v("Here is an example using the "),e("code",[t._v("AsyncHttpClient")]),t._v(" backend for "),e("code",[t._v("ZIO")]),t._v(":")]),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 keyword"}},[t._v("import")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("client"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("client"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("asynchttpclient"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("zio"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("AsyncHttpClientZioBackend\n\nAsyncHttpClientZioBackend"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("flatMap "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" backend "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" serverUrl "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" uri"),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://localhost:8088/api/graphql"')]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" result"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Task"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterView"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n query"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toRequest"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("serverUrl"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("send"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("body"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("absolve\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("As a result, we get a ZIO "),e("code",[t._v("Task")]),t._v(" whose return type is the same as our "),e("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(" "),e("p",[t._v("The "),e("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/",target:"_blank",rel:"noopener noreferrer"}},[t._v("examples"),e("OutboundLink")],1),t._v(" project contains a runnable sample code that queries the example GraphQL backend.")]),t._v(" "),e("div",{staticClass:"custom-block warning"},[e("p",{staticClass:"custom-block-title"},[t._v("Limitations")]),t._v(" "),e("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(" "),e("p",[t._v("Type extensions are not supported by the codegen tool.")])]),t._v(" "),e("h2",{attrs:{id:"laminext-integration"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#laminext-integration"}},[t._v("#")]),t._v(" Laminext Integration")]),t._v(" "),e("p",[t._v("If you are using the Scala.js framework "),e("a",{attrs:{href:"https://laminar.dev",target:"_blank",rel:"noopener noreferrer"}},[t._v("Laminar"),e("OutboundLink")],1),t._v(", there is a module that makes the integration even nicer, with support for subscriptions.\nIt is depending on "),e("a",{attrs:{href:"https://laminext.dev",target:"_blank",rel:"noopener noreferrer"}},[t._v("Laminext"),e("OutboundLink")],1),t._v(", a library that provides nice little helpers for Laminar, in particular for using "),e("code",[t._v("Fetch")]),t._v(" and "),e("code",[t._v("WebSocket")]),t._v(".")]),t._v(" "),e("p",[t._v("To use it, import the "),e("code",[t._v("caliban-client-laminext")]),t._v(" module:")]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v('libraryDependencies += "com.github.ghostdogpr" %%% "caliban-client-laminext" % "1.2.1"\n')])])]),e("p",[t._v("Add the following import to your code:")]),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 keyword"}},[t._v("import")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("client"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("laminext"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n")])])]),e("p",[t._v("This import adds an extension method "),e("code",[t._v("toEventStream(uri)")]),t._v(" to "),e("code",[t._v("SelectionBuilder")]),t._v(", which is similar to "),e("code",[t._v("toRequest")]),t._v(" except it creates an "),e("code",[t._v("EventStream")]),t._v(" instead of an sttp "),e("code",[t._v("Request")]),t._v(".")]),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 keyword"}},[t._v("val")]),t._v(" characters"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Var"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Var"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Nil"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" uri "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://localhost:8088/api/graphql"')]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" getCharacters "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("None"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Client"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toEventStream"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("uri"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" view"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Div "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" \n div"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Characters: "')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n getCharacters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("collectRight "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" characters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("set _"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n child "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" characters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("signal"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" div"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mkString"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('", "')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("To use subscriptions, you first need to create a "),e("code",[t._v("WebSocket")]),t._v(" with protocol "),e("code",[t._v("graphql-ws")]),t._v(". Use the extension method "),e("code",[t._v(".graphql")]),t._v(" instead of "),e("code",[t._v(".text")]),t._v(" or "),e("code",[t._v(".json")]),t._v(".\nThen use the extension method "),e("code",[t._v("toSubscription")]),t._v(" on your "),e("code",[t._v("SelectionBuilder")]),t._v(" and pass the "),e("code",[t._v("WebSocket")]),t._v(" object.")]),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 keyword"}},[t._v("val")]),t._v(" ws "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" WebSocket"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("url"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ws://localhost:8088/ws/graphql"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"graphql-ws"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("graphql"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("build"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" deletedCharacters "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Subscriptions"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characterDeleted"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toSubscription"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ws"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("Finally, you can use "),e("code",[t._v("ws.connect")]),t._v(" to connect the "),e("code",[t._v("WebSocket")]),t._v(", "),e("code",[t._v("ws.init()")]),t._v(" to initialize the communication with the graphql server and "),e("code",[t._v(".received")]),t._v(" to get an "),e("code",[t._v("EventStream")]),t._v(" of the type returned by your subscription.")]),t._v(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[t._v("ws"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("connect"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\nws"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("connected "),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 punctuation"}},[t._v("(")]),t._v("_ "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ws"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("init"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\ndeletedCharacters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("received"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("collectRight "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" \n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" characters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("update"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("filterNot"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_ "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" name"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n")])])]),e("p",[t._v("There is a full example in the "),e("code",[t._v("test")]),t._v(" folder of the "),e("code",[t._v("caliban-client-laminext")]),t._v(" module.\nTo use it:")]),t._v(" "),e("ul",[e("li",[t._v("run "),e("code",[t._v("ExampleApp")]),t._v(" of the http4s server example (it supports CORS)")]),t._v(" "),e("li",[t._v("run "),e("code",[t._v("clientLaminextJS/Test/fastLinkJS")]),t._v(" to compile the Scala.js code")]),t._v(" "),e("li",[t._v("run "),e("code",[t._v("yarn install")]),t._v(" and "),e("code",[t._v("yarn exec vite")]),t._v(" in the "),e("code",[t._v("caliban-client-laminext")]),t._v(" folder")]),t._v(" "),e("li",[t._v("the example page will be running on "),e("a",{attrs:{href:"http://localhost:3000",target:"_blank",rel:"noopener noreferrer"}},[t._v("http://localhost:3000"),e("OutboundLink")],1)])])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/11.f3bf0108.js b/docs/assets/js/11.6f1922be.js similarity index 97% rename from docs/assets/js/11.f3bf0108.js rename to docs/assets/js/11.6f1922be.js index 1e84648609..c80a7d974d 100644 --- a/docs/assets/js/11.f3bf0108.js +++ b/docs/assets/js/11.6f1922be.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[11],{384:function(e,t,a){"use strict";a.r(t);var r=a(46),n=Object(r.a)({},(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[a("h1",{attrs:{id:"examples"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#examples"}},[e._v("#")]),e._v(" Examples")]),e._v(" "),a("p",[e._v("The "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/",target:"_blank",rel:"noopener noreferrer"}},[e._v("examples"),a("OutboundLink")],1),e._v(" project in Github contains various examples:")]),e._v(" "),a("ul",[a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/http4s",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with http4s"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/akkahttp",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with Akka HTTP"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/play",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with play"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/rlavolee/caliban-play-with-route-file",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with play's route file"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/ziohttp",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with zio-http"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/client",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL Client usage"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/client-laminext/src/test/scala/caliban/client/laminext",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL Client integration with Laminext"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/optimizations",target:"_blank",rel:"noopener noreferrer"}},[e._v("Optimization with ZQuery"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/interop/cats",target:"_blank",rel:"noopener noreferrer"}},[e._v("Interop with Cats Effect"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/tapir",target:"_blank",rel:"noopener noreferrer"}},[e._v("Interop with Tapir"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/federation",target:"_blank",rel:"noopener noreferrer"}},[e._v("Apollo Federation usage"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/stitching",target:"_blank",rel:"noopener noreferrer"}},[e._v("Schema Stitching usage"),a("OutboundLink")],1)])]),e._v(" "),a("h4",{attrs:{id:"available-only-with-cats-effect-2-x"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#available-only-with-cats-effect-2-x"}},[e._v("#")]),e._v(" Available only with cats-effect 2.x")]),e._v(" "),a("ul",[a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/interop/monix",target:"_blank",rel:"noopener noreferrer"}},[e._v("Interop with Monix"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/finch",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with finch"),a("OutboundLink")],1)])]),e._v(" "),a("p",[e._v("You may also check out "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban-blog-series",target:"_blank",rel:"noopener noreferrer"}},[e._v("the repository"),a("OutboundLink")],1),e._v(" accompanying my "),a("a",{attrs:{href:"https://medium.com/@ghostdogpr/graphql-in-scala-with-caliban-part-1-8ceb6099c3c2",target:"_blank",rel:"noopener noreferrer"}},[e._v("blog series"),a("OutboundLink")],1),e._v(" on Caliban.")])])}),[],!1,null,null,null);t.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[11],{396:function(e,t,a){"use strict";a.r(t);var r=a(54),n=Object(r.a)({},(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[a("h1",{attrs:{id:"examples"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#examples"}},[e._v("#")]),e._v(" Examples")]),e._v(" "),a("p",[e._v("The "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/",target:"_blank",rel:"noopener noreferrer"}},[e._v("examples"),a("OutboundLink")],1),e._v(" project in Github contains various examples:")]),e._v(" "),a("ul",[a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/http4s",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with http4s"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/akkahttp",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with Akka HTTP"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/play",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with play"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/rlavolee/caliban-play-with-route-file",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with play's route file"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/ziohttp",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with zio-http"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/client",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL Client usage"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/client-laminext/src/test/scala/caliban/client/laminext",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL Client integration with Laminext"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/optimizations",target:"_blank",rel:"noopener noreferrer"}},[e._v("Optimization with ZQuery"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/interop/cats",target:"_blank",rel:"noopener noreferrer"}},[e._v("Interop with Cats Effect"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/tapir",target:"_blank",rel:"noopener noreferrer"}},[e._v("Interop with Tapir"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/federation",target:"_blank",rel:"noopener noreferrer"}},[e._v("Apollo Federation usage"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/stitching",target:"_blank",rel:"noopener noreferrer"}},[e._v("Schema Stitching usage"),a("OutboundLink")],1)])]),e._v(" "),a("h4",{attrs:{id:"available-only-with-cats-effect-2-x"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#available-only-with-cats-effect-2-x"}},[e._v("#")]),e._v(" Available only with cats-effect 2.x")]),e._v(" "),a("ul",[a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/interop/monix",target:"_blank",rel:"noopener noreferrer"}},[e._v("Interop with Monix"),a("OutboundLink")],1)]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/finch",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with finch"),a("OutboundLink")],1)])]),e._v(" "),a("p",[e._v("You may also check out "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban-blog-series",target:"_blank",rel:"noopener noreferrer"}},[e._v("the repository"),a("OutboundLink")],1),e._v(" accompanying my "),a("a",{attrs:{href:"https://medium.com/@ghostdogpr/graphql-in-scala-with-caliban-part-1-8ceb6099c3c2",target:"_blank",rel:"noopener noreferrer"}},[e._v("blog series"),a("OutboundLink")],1),e._v(" on Caliban.")])])}),[],!1,null,null,null);t.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/12.c729c0a9.js b/docs/assets/js/12.88935583.js similarity index 99% rename from docs/assets/js/12.c729c0a9.js rename to docs/assets/js/12.88935583.js index d645d9a94c..f26690e48b 100644 --- a/docs/assets/js/12.c729c0a9.js +++ b/docs/assets/js/12.88935583.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[12],{385:function(t,a,e){"use strict";e.r(a);var s=e(46),n=Object(s.a)({},(function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"federation"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#federation"}},[t._v("#")]),t._v(" Federation")]),t._v(" "),e("p",[e("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(" "),e("h2",{attrs:{id:"dependencies"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#dependencies"}},[t._v("#")]),t._v(" Dependencies")]),t._v(" "),e("p",[e("code",[t._v("caliban-federation")]),t._v(" only depends on "),e("code",[t._v("caliban-core")]),t._v(" and is very unobtrusive.")]),t._v(" "),e("p",[t._v("To use, add the following line to your "),e("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v('libraryDependencies += "com.github.ghostdogpr" %% "caliban-federation" % "1.2.1"\n')])])]),e("h2",{attrs:{id:"federating"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#federating"}},[t._v("#")]),t._v(" Federating")]),t._v(" "),e("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(" "),e("p",[t._v("You can read more about federation and why it may be useful "),e("a",{attrs:{href:"https://www.apollographql.com/docs/apollo-server/federation/introduction/",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),e("OutboundLink")],1),t._v(".")]),t._v(" "),e("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(" "),e("p",[t._v("If you already have a graph you can add federation simply by calling the wrapper function "),e("code",[t._v("federate")])]),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 keyword"}},[t._v("import")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("federation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schema"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Queries"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n characters "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Amos"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" federatedSchema"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" federate"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("schema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("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(" "),e("p",[t._v('First, any types that will be "resolvable" need to be annotated with a '),e("code",[t._v("@key")]),t._v(" directive. You can use a helper function found\nin the "),e("code",[t._v("federation")]),t._v(" package to help with that.")]),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 annotation punctuation"}},[t._v("@GQLDirective")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Key"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("The "),e("code",[t._v('"name"')]),t._v(" field is a field selector minus the outer braces.")]),t._v(" "),e("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 "),e("code",[t._v("@extends")]),t._v(" annotation")]),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 annotation punctuation"}},[t._v("@GQLDirective")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Key"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"season episode"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n"),e("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLDirective")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Extend"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Episode"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLDirective")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("External"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" season"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLDirective")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("External"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" episode"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cast"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("Note the additional annotations we needed in this case. "),e("code",[t._v("Extend")]),t._v(" is needed to tell the gateway that this type is defined within\nanother service, while the "),e("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(" "),e("p",[t._v("Once you have annotated your types, you need to tell "),e("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 "),e("code",[t._v("EntityResolver")]),t._v(":")]),t._v(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[t._v("EntityResolver"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterService"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CharacterArgs"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" \n ZQuery"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromEffect"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getCharacter"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n")])])]),e("p",[e("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(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[t._v("EntityResolver"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromMetadata"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterArgs"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" args "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fields"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("forall"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" ZQuery"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Nil"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" ZQuery"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromEffect"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getCharacter"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("In the above we need to define an resolver which takes an "),e("code",[t._v("R")]),t._v(" environment type,\nan "),e("code",[t._v("A")]),t._v(" which has an implicit "),e("code",[t._v("ArgBuilder")]),t._v(" and an "),e("code",[t._v("Option[Out]")]),t._v(" where "),e("code",[t._v("Out")]),t._v(" has an implicit\n"),e("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(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[t._v("federate"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("schema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" aResolver"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" additionalResolvers"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("_"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("You can now use the resulting "),e("code",[t._v("GraphQL[R]")]),t._v(" to start querying. You can also see the full code example "),e("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/federation",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),e("OutboundLink")],1)]),t._v(" "),e("h2",{attrs:{id:"tracing"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#tracing"}},[t._v("#")]),t._v(" Tracing")]),t._v(" "),e("p",[t._v("Federated tracing is slightly different from standard apollo-tracing thus it comes with its own wrapper defined in the "),e("code",[t._v("caliban-federation")]),t._v(" module.")]),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 keyword"}},[t._v("import")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("federation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tracing"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ApolloFederatedTracing\n\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" federate"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("schema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" resolver"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" additionalResolvers"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" _"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@ ApolloFederatedTracing"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrapper\n")])])]),e("p",[t._v("In federated tracing the gateway communicates with the implementing service via a header "),e("code",[t._v("apollo-federation-include-trace")]),t._v(",\nfor now the only value it can send is "),e("code",[t._v("ftv1")]),t._v(". Thus if you detect this header then you should enable tracing otherwise you can disable it.")]),t._v(" "),e("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 "),e("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(" "),e("p",[t._v("If you wish to enable it manually (after detecting the header with your preferred framework) you can call: "),e("code",[t._v("request.withFederatedTracing")]),t._v(" which will return a new "),e("code",[t._v("GraphQLRequest")]),t._v(" that informs the wrapper\nthat it should include tracing data as part of the response extensions.")])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[12],{397:function(t,a,e){"use strict";e.r(a);var s=e(54),n=Object(s.a)({},(function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"federation"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#federation"}},[t._v("#")]),t._v(" Federation")]),t._v(" "),e("p",[e("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(" "),e("h2",{attrs:{id:"dependencies"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#dependencies"}},[t._v("#")]),t._v(" Dependencies")]),t._v(" "),e("p",[e("code",[t._v("caliban-federation")]),t._v(" only depends on "),e("code",[t._v("caliban-core")]),t._v(" and is very unobtrusive.")]),t._v(" "),e("p",[t._v("To use, add the following line to your "),e("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v('libraryDependencies += "com.github.ghostdogpr" %% "caliban-federation" % "1.2.1"\n')])])]),e("h2",{attrs:{id:"federating"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#federating"}},[t._v("#")]),t._v(" Federating")]),t._v(" "),e("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(" "),e("p",[t._v("You can read more about federation and why it may be useful "),e("a",{attrs:{href:"https://www.apollographql.com/docs/apollo-server/federation/introduction/",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),e("OutboundLink")],1),t._v(".")]),t._v(" "),e("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(" "),e("p",[t._v("If you already have a graph you can add federation simply by calling the wrapper function "),e("code",[t._v("federate")])]),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 keyword"}},[t._v("import")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("federation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schema"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Queries"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n characters "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Amos"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" federatedSchema"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" federate"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("schema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("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(" "),e("p",[t._v('First, any types that will be "resolvable" need to be annotated with a '),e("code",[t._v("@key")]),t._v(" directive. You can use a helper function found\nin the "),e("code",[t._v("federation")]),t._v(" package to help with that.")]),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 annotation punctuation"}},[t._v("@GQLDirective")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Key"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("The "),e("code",[t._v('"name"')]),t._v(" field is a field selector minus the outer braces.")]),t._v(" "),e("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 "),e("code",[t._v("@extends")]),t._v(" annotation")]),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 annotation punctuation"}},[t._v("@GQLDirective")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Key"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"season episode"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n"),e("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLDirective")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Extend"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Episode"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLDirective")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("External"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" season"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLDirective")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("External"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" episode"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cast"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("Note the additional annotations we needed in this case. "),e("code",[t._v("Extend")]),t._v(" is needed to tell the gateway that this type is defined within\nanother service, while the "),e("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(" "),e("p",[t._v("Once you have annotated your types, you need to tell "),e("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 "),e("code",[t._v("EntityResolver")]),t._v(":")]),t._v(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[t._v("EntityResolver"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterService"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CharacterArgs"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" \n ZQuery"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromEffect"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getCharacter"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n")])])]),e("p",[e("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(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[t._v("EntityResolver"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromMetadata"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CharacterArgs"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" args "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fields"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("forall"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" ZQuery"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Character"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Nil"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" ZQuery"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromEffect"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getCharacter"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("In the above we need to define an resolver which takes an "),e("code",[t._v("R")]),t._v(" environment type,\nan "),e("code",[t._v("A")]),t._v(" which has an implicit "),e("code",[t._v("ArgBuilder")]),t._v(" and an "),e("code",[t._v("Option[Out]")]),t._v(" where "),e("code",[t._v("Out")]),t._v(" has an implicit\n"),e("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(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[t._v("federate"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("schema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" aResolver"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" additionalResolvers"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("_"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("You can now use the resulting "),e("code",[t._v("GraphQL[R]")]),t._v(" to start querying. You can also see the full code example "),e("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/federation",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),e("OutboundLink")],1)]),t._v(" "),e("h2",{attrs:{id:"tracing"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#tracing"}},[t._v("#")]),t._v(" Tracing")]),t._v(" "),e("p",[t._v("Federated tracing is slightly different from standard apollo-tracing thus it comes with its own wrapper defined in the "),e("code",[t._v("caliban-federation")]),t._v(" module.")]),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 keyword"}},[t._v("import")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("federation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tracing"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ApolloFederatedTracing\n\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" federate"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("schema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" resolver"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" additionalResolvers"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" _"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@ ApolloFederatedTracing"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrapper\n")])])]),e("p",[t._v("In federated tracing the gateway communicates with the implementing service via a header "),e("code",[t._v("apollo-federation-include-trace")]),t._v(",\nfor now the only value it can send is "),e("code",[t._v("ftv1")]),t._v(". Thus if you detect this header then you should enable tracing otherwise you can disable it.")]),t._v(" "),e("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 "),e("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(" "),e("p",[t._v("If you wish to enable it manually (after detecting the header with your preferred framework) you can call: "),e("code",[t._v("request.withFederatedTracing")]),t._v(" which will return a new "),e("code",[t._v("GraphQLRequest")]),t._v(" that informs the wrapper\nthat it should include tracing data as part of the response extensions.")])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/13.4eb72b62.js b/docs/assets/js/13.550a76f2.js similarity index 99% rename from docs/assets/js/13.4eb72b62.js rename to docs/assets/js/13.550a76f2.js index a7444f2f12..bdc2b1a98d 100644 --- a/docs/assets/js/13.4eb72b62.js +++ b/docs/assets/js/13.550a76f2.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[13],{386:function(t,a,s){"use strict";s.r(a);var n=s(46),e=Object(n.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"interop"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#interop"}},[t._v("#")]),t._v(" Interop")]),t._v(" "),s("p",[t._v("If you prefer using "),s("a",{attrs:{href:"https://github.com/typelevel/cats-effect",target:"_blank",rel:"noopener noreferrer"}},[t._v("Cats Effect"),s("OutboundLink")],1),t._v(" or "),s("a",{attrs:{href:"https://github.com/monix/monix",target:"_blank",rel:"noopener noreferrer"}},[t._v("Monix"),s("OutboundLink")],1),t._v(" rather than ZIO, you can use the respective "),s("code",[t._v("caliban-cats")]),t._v(" and "),s("code",[t._v("caliban-monix")]),t._v(" modules.")]),t._v(" "),s("p",[t._v("The "),s("code",[t._v("caliban-tapir")]),t._v(" module allows converting your "),s("a",{attrs:{href:"https://github.com/softwaremill/tapir",target:"_blank",rel:"noopener noreferrer"}},[t._v("Tapir"),s("OutboundLink")],1),t._v(" endpoints into a GraphQL API.")]),t._v(" "),s("h2",{attrs:{id:"cats-effect"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#cats-effect"}},[t._v("#")]),t._v(" Cats Effect")]),t._v(" "),s("p",[t._v("You first need to import "),s("code",[t._v("caliban.interop.cats.implicits._")]),t._v(" and have an implicit "),s("code",[t._v("zio.Runtime")]),t._v(" in scope. Then a few helpers are available:")]),t._v(" "),s("ul",[s("li",[t._v("the "),s("code",[t._v("GraphQL")]),t._v(" object is enriched with "),s("code",[t._v("interpreterAsync")]),t._v(", a variant of "),s("code",[t._v("interpreter")]),t._v(" that return an "),s("code",[t._v("F[_]: Async")]),t._v(" instead of a "),s("code",[t._v("ZIO")]),t._v(".")]),t._v(" "),s("li",[t._v("the "),s("code",[t._v("GraphQLInterpreter")]),t._v(" object is enriched with "),s("code",[t._v("executeAsync")]),t._v(" and "),s("code",[t._v("checkAsync")]),t._v(", variants of "),s("code",[t._v("execute")]),t._v(" and "),s("code",[t._v("check")]),t._v(" that return an "),s("code",[t._v("F[_]: Async")]),t._v(" instead of a "),s("code",[t._v("ZIO")]),t._v(".")]),t._v(" "),s("li",[t._v("the "),s("code",[t._v("Http4sAdapter")]),t._v(" also has cats-effect variants named "),s("code",[t._v("makeRestServiceF")]),t._v(" and "),s("code",[t._v("makeWebSocketServiceF")]),t._v(".")])]),t._v(" "),s("p",[t._v("In addition to that, a "),s("code",[t._v("Schema")]),t._v(" for any "),s("code",[t._v("F[_]: Effect")]),t._v(" is provided. That means you can include fields with results wrapped in "),s("code",[t._v("F")]),t._v(" in your queries, mutations or subscriptions.")]),t._v(" "),s("p",[t._v("The following example shows how to create an interpreter and run a query while only using Cats IO.")]),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("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("GraphQL"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("graphQL\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("RootResolver\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("interop"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cats"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("implicits"),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("cats"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("effect"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" ExitCode"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IOApp "),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("cats"),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("std"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Dispatcher\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("Runtime\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" ExampleCatsInterop "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" IOApp "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\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(" zioRuntime "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Runtime"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("default\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("numbers"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" randomNumber"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" IO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),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(" queries "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("scala"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("util"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Random"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nextInt"),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(")")]),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(" query "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token triple-quoted-string string"}},[t._v('"""\n {\n numbers\n randomNumber\n }"""')]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" run"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),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("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" IO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ExitCode"),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 Dispatcher"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("IO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("use "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" dispatcher "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// required for a derivation of the schema")]),t._v("\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("(")]),t._v("RootResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\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 interpreter "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interpreterAsync"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("IO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n result "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" interpreter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("executeAsync"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("IO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),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("\n _ "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" IO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("println"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),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 punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" ExitCode"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Success\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("You can find this example within the "),s("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/blob/master/examples/src/main/scala/example/interop/cats/ExampleCatsInterop.scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("examples"),s("OutboundLink")],1),t._v(" project.")]),t._v(" "),s("h2",{attrs:{id:"monix-only-with-cats-effect-2-x"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#monix-only-with-cats-effect-2-x"}},[t._v("#")]),t._v(" Monix (only with cats-effect 2.x)")]),t._v(" "),s("p",[t._v("You first need to import "),s("code",[t._v("caliban.interop.monix.implicits._")]),t._v(" and have an implicit "),s("code",[t._v("zio.Runtime")]),t._v(" in scope. Then a few helpers are available:")]),t._v(" "),s("ul",[s("li",[t._v("the "),s("code",[t._v("GraphQL")]),t._v(" object is enriched with "),s("code",[t._v("interpreterAsync")]),t._v(", a variant of "),s("code",[t._v("interpreter")]),t._v(" that return a Monix "),s("code",[t._v("Task")]),t._v(" instead of a "),s("code",[t._v("ZIO")]),t._v(".")]),t._v(" "),s("li",[t._v("the "),s("code",[t._v("GraphQLInterpreter")]),t._v(" object is enriched with "),s("code",[t._v("executeAsync")]),t._v(" and "),s("code",[t._v("checkAsync")]),t._v(", variants of "),s("code",[t._v("execute")]),t._v(" and "),s("code",[t._v("check")]),t._v(" that return a Monix "),s("code",[t._v("Task")]),t._v(" instead of a "),s("code",[t._v("ZIO")]),t._v(".")])]),t._v(" "),s("p",[t._v("In addition to that, a "),s("code",[t._v("Schema")]),t._v(" for any Monix "),s("code",[t._v("Task")]),t._v(" as well as "),s("code",[t._v("Observable")]),t._v(" is provided.")]),t._v(" "),s("p",[t._v("The following example shows how to create an interpreter and run a query while only using Monix Task.")]),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("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("GraphQL"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("graphQL\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("RootResolver\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("interop"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("monix"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("implicits"),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("cats"),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("ExitCode\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("monix"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("eval"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" Task"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" TaskApp "),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("monix"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("execution"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Scheduler\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("Runtime\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" ExampleMonixInterop "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" TaskApp "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\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(" zioRuntime "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Runtime"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("default\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(" monixScheduler"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Scheduler "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" scheduler\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("numbers"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" randomNumber"),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("Int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),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(" queries "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Task"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("eval"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("scala"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("util"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Random"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nextInt"),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(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\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("(")]),t._v("RootResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),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(" query "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token triple-quoted-string string"}},[t._v('"""\n {\n numbers\n randomNumber\n }"""')]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" run"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),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("]")]),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("[")]),t._v("ExitCode"),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 "),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 interpreter "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interpreterAsync\n result "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" interpreter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("executeAsync"),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("\n _ "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" Task"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("eval"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("println"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),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 punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" ExitCode"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Success\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("You can find this example within the "),s("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/blob/master/examples/src/main/scala/example/interop/monix/ExampleMonixInterop.scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("examples"),s("OutboundLink")],1),t._v(" project.")]),t._v(" "),s("h2",{attrs:{id:"tapir"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#tapir"}},[t._v("#")]),t._v(" Tapir")]),t._v(" "),s("p",[t._v("After adding the "),s("code",[t._v("caliban-tapir")]),t._v(" dependency to your build, adding "),s("code",[t._v("import caliban.interop.tapir._")]),t._v(" to your code will introduce an extension method called "),s("code",[t._v("toGraphQL")]),t._v(" on Tapir's "),s("code",[t._v("Endpoint")]),t._v(" and "),s("code",[t._v("ServerEndpoint")]),t._v(".\nThis method will convert your endpoint into a "),s("code",[t._v("GraphQL")]),t._v(" object that you can then combine and expose.")]),t._v(" "),s("p",[t._v("The conversion rules are the following:")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("GET")]),t._v(" endpoints are turned into Queries")]),t._v(" "),s("li",[s("code",[t._v("PUT")]),t._v(", "),s("code",[t._v("POST")]),t._v(" and "),s("code",[t._v("DELETE")]),t._v(" endpoints are turned into Mutations")]),t._v(" "),s("li",[t._v("fixed query paths are used to name GraphQL fields (e.g. an endpoint "),s("code",[t._v("/book/add")]),t._v(" will give a GraphQL field named "),s("code",[t._v("bookAdd")]),t._v(")")]),t._v(" "),s("li",[t._v("query parameters, headers, cookies and request body are used as GraphQL arguments")]),t._v(" "),s("li",[t._v("there should be an implicit "),s("code",[t._v("Schema")]),t._v(" for both the input and the output types and an implicit "),s("code",[t._v("ArgBuilder")]),t._v(" for the input type (see the "),s("RouterLink",{attrs:{to:"/docs/schema.html"}},[t._v("dedicated docs")]),t._v(")")],1)]),t._v(" "),s("p",[t._v("Let's look at an example. Imagine we have the following Tapir endpoint:")]),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(" addBook"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Endpoint"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Book"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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 punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),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 infallibleEndpoint\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("post\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("in"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"books"')]),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("in"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"add"')]),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("in"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n jsonBody"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Book"),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("description"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"The book to add"')]),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("example"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Book"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Pride and Prejudice"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1813")]),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 punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("in"),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 builtin"}},[t._v("String")]),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 string"}},[t._v('"X-Auth-Token"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("description"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"The token is 'secret'\"")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("And a possible implementation:")]),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("def")]),t._v(" bookAddLogic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("book"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Book"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" token"),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(" UIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),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("Just like you can create an http4s route by calling "),s("code",[t._v("toRoute")]),t._v(" and passing an implementation, call "),s("code",[t._v("toGraphQL")]),t._v(" to create a GraphQL API:")]),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(" 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(" addBook"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toGraphQL"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("bookAddLogic _"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tupled"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("That's it! You can combine multiple "),s("code",[t._v("GraphQL")]),t._v(" objects using "),s("code",[t._v("|+|")]),t._v(" and expose the result using one of Caliban's adapters.")]),t._v(" "),s("p",[t._v("If you want to reuse "),s("code",[t._v("bookAddLogic")]),t._v(" for both GraphQL and regular HTTP, you can turn your "),s("code",[t._v("Endpoint")]),t._v(" into a "),s("code",[t._v("ServerEndpoint")]),t._v(" by calling "),s("code",[t._v(".serverLogic")]),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("val")]),t._v(" addBookEndpoint"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ServerEndpoint"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Book"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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 punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" UIO"),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 addBook"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("serverLogic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("UIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("book"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" token"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" bookAddLogic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("book"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" token"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("either "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("This can then be used to generate both an HTTP route (e.g. "),s("code",[t._v("toRoutes")]),t._v(" with http4s) and a GraphQL API ("),s("code",[t._v(".toGraphQL")]),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("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(" addBookEndpoint"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toGraphQL\n")])])]),s("p",[t._v("You can find a "),s("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/tapir",target:"_blank",rel:"noopener noreferrer"}},[t._v("full example"),s("OutboundLink")],1),t._v(" on github.")]),t._v(" "),s("h3",{attrs:{id:"graphql-restrictions"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#graphql-restrictions"}},[t._v("#")]),t._v(" GraphQL restrictions")]),t._v(" "),s("p",[s("a",{attrs:{href:"https://spec.graphql.org/June2018/#sec-Operation-Name-Uniqueness",target:"_blank",rel:"noopener noreferrer"}},[t._v("GraphQL spec"),s("OutboundLink")],1),t._v(" requires unique naming for all operations.")]),t._v(" "),s("p",[t._v("To customize the "),s("a",{attrs:{href:"https://github.com/softwaremill/tapir/blob/master/core/src/main/scala/sttp/tapir/Endpoint.scala#L287",target:"_blank",rel:"noopener noreferrer"}},[t._v("name"),s("OutboundLink")],1),t._v(" of an operation use "),s("code",[t._v("EndpointInfo.name")])]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[t._v("endpoint\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"overrideName"')]),s("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([[13],{398:function(t,a,s){"use strict";s.r(a);var n=s(54),e=Object(n.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"interop"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#interop"}},[t._v("#")]),t._v(" Interop")]),t._v(" "),s("p",[t._v("If you prefer using "),s("a",{attrs:{href:"https://github.com/typelevel/cats-effect",target:"_blank",rel:"noopener noreferrer"}},[t._v("Cats Effect"),s("OutboundLink")],1),t._v(" or "),s("a",{attrs:{href:"https://github.com/monix/monix",target:"_blank",rel:"noopener noreferrer"}},[t._v("Monix"),s("OutboundLink")],1),t._v(" rather than ZIO, you can use the respective "),s("code",[t._v("caliban-cats")]),t._v(" and "),s("code",[t._v("caliban-monix")]),t._v(" modules.")]),t._v(" "),s("p",[t._v("The "),s("code",[t._v("caliban-tapir")]),t._v(" module allows converting your "),s("a",{attrs:{href:"https://github.com/softwaremill/tapir",target:"_blank",rel:"noopener noreferrer"}},[t._v("Tapir"),s("OutboundLink")],1),t._v(" endpoints into a GraphQL API.")]),t._v(" "),s("h2",{attrs:{id:"cats-effect"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#cats-effect"}},[t._v("#")]),t._v(" Cats Effect")]),t._v(" "),s("p",[t._v("You first need to import "),s("code",[t._v("caliban.interop.cats.implicits._")]),t._v(" and have an implicit "),s("code",[t._v("zio.Runtime")]),t._v(" in scope. Then a few helpers are available:")]),t._v(" "),s("ul",[s("li",[t._v("the "),s("code",[t._v("GraphQL")]),t._v(" object is enriched with "),s("code",[t._v("interpreterAsync")]),t._v(", a variant of "),s("code",[t._v("interpreter")]),t._v(" that return an "),s("code",[t._v("F[_]: Async")]),t._v(" instead of a "),s("code",[t._v("ZIO")]),t._v(".")]),t._v(" "),s("li",[t._v("the "),s("code",[t._v("GraphQLInterpreter")]),t._v(" object is enriched with "),s("code",[t._v("executeAsync")]),t._v(" and "),s("code",[t._v("checkAsync")]),t._v(", variants of "),s("code",[t._v("execute")]),t._v(" and "),s("code",[t._v("check")]),t._v(" that return an "),s("code",[t._v("F[_]: Async")]),t._v(" instead of a "),s("code",[t._v("ZIO")]),t._v(".")]),t._v(" "),s("li",[t._v("the "),s("code",[t._v("Http4sAdapter")]),t._v(" also has cats-effect variants named "),s("code",[t._v("makeRestServiceF")]),t._v(" and "),s("code",[t._v("makeWebSocketServiceF")]),t._v(".")])]),t._v(" "),s("p",[t._v("In addition to that, a "),s("code",[t._v("Schema")]),t._v(" for any "),s("code",[t._v("F[_]: Effect")]),t._v(" is provided. That means you can include fields with results wrapped in "),s("code",[t._v("F")]),t._v(" in your queries, mutations or subscriptions.")]),t._v(" "),s("p",[t._v("The following example shows how to create an interpreter and run a query while only using Cats IO.")]),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("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("GraphQL"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("graphQL\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("RootResolver\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("interop"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cats"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("implicits"),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("cats"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("effect"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" ExitCode"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IOApp "),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("cats"),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("std"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Dispatcher\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("Runtime\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" ExampleCatsInterop "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" IOApp "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\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(" zioRuntime "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Runtime"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("default\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("numbers"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" randomNumber"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" IO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),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(" queries "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("scala"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("util"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Random"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nextInt"),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(")")]),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(" query "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token triple-quoted-string string"}},[t._v('"""\n {\n numbers\n randomNumber\n }"""')]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" run"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),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("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" IO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ExitCode"),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 Dispatcher"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("IO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("use "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" dispatcher "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// required for a derivation of the schema")]),t._v("\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("(")]),t._v("RootResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\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 interpreter "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interpreterAsync"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("IO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n result "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" interpreter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("executeAsync"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("IO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),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("\n _ "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" IO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("println"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),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 punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" ExitCode"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Success\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("You can find this example within the "),s("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/blob/master/examples/src/main/scala/example/interop/cats/ExampleCatsInterop.scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("examples"),s("OutboundLink")],1),t._v(" project.")]),t._v(" "),s("h2",{attrs:{id:"monix-only-with-cats-effect-2-x"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#monix-only-with-cats-effect-2-x"}},[t._v("#")]),t._v(" Monix (only with cats-effect 2.x)")]),t._v(" "),s("p",[t._v("You first need to import "),s("code",[t._v("caliban.interop.monix.implicits._")]),t._v(" and have an implicit "),s("code",[t._v("zio.Runtime")]),t._v(" in scope. Then a few helpers are available:")]),t._v(" "),s("ul",[s("li",[t._v("the "),s("code",[t._v("GraphQL")]),t._v(" object is enriched with "),s("code",[t._v("interpreterAsync")]),t._v(", a variant of "),s("code",[t._v("interpreter")]),t._v(" that return a Monix "),s("code",[t._v("Task")]),t._v(" instead of a "),s("code",[t._v("ZIO")]),t._v(".")]),t._v(" "),s("li",[t._v("the "),s("code",[t._v("GraphQLInterpreter")]),t._v(" object is enriched with "),s("code",[t._v("executeAsync")]),t._v(" and "),s("code",[t._v("checkAsync")]),t._v(", variants of "),s("code",[t._v("execute")]),t._v(" and "),s("code",[t._v("check")]),t._v(" that return a Monix "),s("code",[t._v("Task")]),t._v(" instead of a "),s("code",[t._v("ZIO")]),t._v(".")])]),t._v(" "),s("p",[t._v("In addition to that, a "),s("code",[t._v("Schema")]),t._v(" for any Monix "),s("code",[t._v("Task")]),t._v(" as well as "),s("code",[t._v("Observable")]),t._v(" is provided.")]),t._v(" "),s("p",[t._v("The following example shows how to create an interpreter and run a query while only using Monix Task.")]),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("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("GraphQL"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("graphQL\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("RootResolver\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("interop"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("monix"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("implicits"),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("cats"),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("ExitCode\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("monix"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("eval"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" Task"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" TaskApp "),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("monix"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("execution"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Scheduler\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("Runtime\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" ExampleMonixInterop "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" TaskApp "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\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(" zioRuntime "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Runtime"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("default\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(" monixScheduler"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Scheduler "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" scheduler\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("numbers"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" randomNumber"),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("Int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),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(" queries "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Task"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("eval"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("scala"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("util"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Random"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nextInt"),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(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\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("(")]),t._v("RootResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),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(" query "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token triple-quoted-string string"}},[t._v('"""\n {\n numbers\n randomNumber\n }"""')]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" run"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),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("]")]),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("[")]),t._v("ExitCode"),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 "),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 interpreter "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interpreterAsync\n result "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" interpreter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("executeAsync"),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("\n _ "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" Task"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("eval"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("println"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),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 punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" ExitCode"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Success\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("You can find this example within the "),s("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/blob/master/examples/src/main/scala/example/interop/monix/ExampleMonixInterop.scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("examples"),s("OutboundLink")],1),t._v(" project.")]),t._v(" "),s("h2",{attrs:{id:"tapir"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#tapir"}},[t._v("#")]),t._v(" Tapir")]),t._v(" "),s("p",[t._v("After adding the "),s("code",[t._v("caliban-tapir")]),t._v(" dependency to your build, adding "),s("code",[t._v("import caliban.interop.tapir._")]),t._v(" to your code will introduce an extension method called "),s("code",[t._v("toGraphQL")]),t._v(" on Tapir's "),s("code",[t._v("Endpoint")]),t._v(" and "),s("code",[t._v("ServerEndpoint")]),t._v(".\nThis method will convert your endpoint into a "),s("code",[t._v("GraphQL")]),t._v(" object that you can then combine and expose.")]),t._v(" "),s("p",[t._v("The conversion rules are the following:")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("GET")]),t._v(" endpoints are turned into Queries")]),t._v(" "),s("li",[s("code",[t._v("PUT")]),t._v(", "),s("code",[t._v("POST")]),t._v(" and "),s("code",[t._v("DELETE")]),t._v(" endpoints are turned into Mutations")]),t._v(" "),s("li",[t._v("fixed query paths are used to name GraphQL fields (e.g. an endpoint "),s("code",[t._v("/book/add")]),t._v(" will give a GraphQL field named "),s("code",[t._v("bookAdd")]),t._v(")")]),t._v(" "),s("li",[t._v("query parameters, headers, cookies and request body are used as GraphQL arguments")]),t._v(" "),s("li",[t._v("there should be an implicit "),s("code",[t._v("Schema")]),t._v(" for both the input and the output types and an implicit "),s("code",[t._v("ArgBuilder")]),t._v(" for the input type (see the "),s("RouterLink",{attrs:{to:"/docs/schema.html"}},[t._v("dedicated docs")]),t._v(")")],1)]),t._v(" "),s("p",[t._v("Let's look at an example. Imagine we have the following Tapir endpoint:")]),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(" addBook"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Endpoint"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Book"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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 punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),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 infallibleEndpoint\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("post\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("in"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"books"')]),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("in"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"add"')]),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("in"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n jsonBody"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Book"),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("description"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"The book to add"')]),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("example"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Book"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Pride and Prejudice"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1813")]),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 punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("in"),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 builtin"}},[t._v("String")]),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 string"}},[t._v('"X-Auth-Token"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("description"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"The token is 'secret'\"")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("And a possible implementation:")]),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("def")]),t._v(" bookAddLogic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("book"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Book"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" token"),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(" UIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),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("Just like you can create an http4s route by calling "),s("code",[t._v("toRoute")]),t._v(" and passing an implementation, call "),s("code",[t._v("toGraphQL")]),t._v(" to create a GraphQL API:")]),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(" 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(" addBook"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toGraphQL"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("bookAddLogic _"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tupled"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("That's it! You can combine multiple "),s("code",[t._v("GraphQL")]),t._v(" objects using "),s("code",[t._v("|+|")]),t._v(" and expose the result using one of Caliban's adapters.")]),t._v(" "),s("p",[t._v("If you want to reuse "),s("code",[t._v("bookAddLogic")]),t._v(" for both GraphQL and regular HTTP, you can turn your "),s("code",[t._v("Endpoint")]),t._v(" into a "),s("code",[t._v("ServerEndpoint")]),t._v(" by calling "),s("code",[t._v(".serverLogic")]),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("val")]),t._v(" addBookEndpoint"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ServerEndpoint"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Book"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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 punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" UIO"),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 addBook"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("serverLogic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("UIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("book"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" token"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" bookAddLogic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("book"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" token"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("either "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("This can then be used to generate both an HTTP route (e.g. "),s("code",[t._v("toRoutes")]),t._v(" with http4s) and a GraphQL API ("),s("code",[t._v(".toGraphQL")]),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("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(" addBookEndpoint"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toGraphQL\n")])])]),s("p",[t._v("You can find a "),s("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/tapir",target:"_blank",rel:"noopener noreferrer"}},[t._v("full example"),s("OutboundLink")],1),t._v(" on github.")]),t._v(" "),s("h3",{attrs:{id:"graphql-restrictions"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#graphql-restrictions"}},[t._v("#")]),t._v(" GraphQL restrictions")]),t._v(" "),s("p",[s("a",{attrs:{href:"https://spec.graphql.org/June2018/#sec-Operation-Name-Uniqueness",target:"_blank",rel:"noopener noreferrer"}},[t._v("GraphQL spec"),s("OutboundLink")],1),t._v(" requires unique naming for all operations.")]),t._v(" "),s("p",[t._v("To customize the "),s("a",{attrs:{href:"https://github.com/softwaremill/tapir/blob/master/core/src/main/scala/sttp/tapir/Endpoint.scala#L287",target:"_blank",rel:"noopener noreferrer"}},[t._v("name"),s("OutboundLink")],1),t._v(" of an operation use "),s("code",[t._v("EndpointInfo.name")])]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[t._v("endpoint\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"overrideName"')]),s("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/14.51224088.js b/docs/assets/js/14.22d76291.js similarity index 89% rename from docs/assets/js/14.51224088.js rename to docs/assets/js/14.22d76291.js index cd92b73162..11c71d32ec 100644 --- a/docs/assets/js/14.51224088.js +++ b/docs/assets/js/14.22d76291.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[14],{387:function(e,t,n){"use strict";n.r(t);var a=n(46),r=Object(a.a)({},(function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[n("h1",{attrs:{id:"introspection"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#introspection"}},[e._v("#")]),e._v(" Introspection")]),e._v(" "),n("p",[e._v("Introspection queries are fully supported, which means you can use your favorite tool to inspect your schema and generate documentation for free.")]),e._v(" "),n("p",[e._v("Here's an example of documentation generated by introspection in "),n("a",{attrs:{href:"https://altair.sirmuel.design/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Altair GraphQL Client"),n("OutboundLink")],1),e._v(":")]),e._v(" "),n("p",[n("img",{attrs:{src:"/caliban/altair.png",alt:"altair screenshot"}})]),e._v(" "),n("p",[e._v("It is possible to disable introspection when executing a query by passing "),n("code",[e._v("enableIntrospection = false")]),e._v(" when calling "),n("code",[e._v("execute")]),e._v(" (also available in the adapters).")])])}),[],!1,null,null,null);t.default=r.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[14],{399:function(e,t,n){"use strict";n.r(t);var a=n(54),r=Object(a.a)({},(function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[n("h1",{attrs:{id:"introspection"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#introspection"}},[e._v("#")]),e._v(" Introspection")]),e._v(" "),n("p",[e._v("Introspection queries are fully supported, which means you can use your favorite tool to inspect your schema and generate documentation for free.")]),e._v(" "),n("p",[e._v("Here's an example of documentation generated by introspection in "),n("a",{attrs:{href:"https://altair.sirmuel.design/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Altair GraphQL Client"),n("OutboundLink")],1),e._v(":")]),e._v(" "),n("p",[n("img",{attrs:{src:"/caliban/altair.png",alt:"altair screenshot"}})]),e._v(" "),n("p",[e._v("It is possible to disable introspection when executing a query by passing "),n("code",[e._v("enableIntrospection = false")]),e._v(" when calling "),n("code",[e._v("execute")]),e._v(" (also available in the adapters).")])])}),[],!1,null,null,null);t.default=r.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/15.126379cb.js b/docs/assets/js/15.23a221ff.js similarity index 99% rename from docs/assets/js/15.126379cb.js rename to docs/assets/js/15.23a221ff.js index da8a0afbe5..0bed082931 100644 --- a/docs/assets/js/15.126379cb.js +++ b/docs/assets/js/15.23a221ff.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[15],{388:function(t,a,s){"use strict";s.r(a);var n=s(46),e=Object(n.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"middleware"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#middleware"}},[t._v("#")]),t._v(" Middleware")]),t._v(" "),s("p",[t._v("Caliban allows you to perform additional actions at various levels of a query processing, via the concept of "),s("code",[t._v("Wrapper")]),t._v(". Using wrappers, you can:")]),t._v(" "),s("ul",[s("li",[t._v("verify that a query doesn't reach some limit (e.g. depth, complexity)")]),t._v(" "),s("li",[t._v("modify a query before it's executed")]),t._v(" "),s("li",[t._v("add timeouts to queries or fields")]),t._v(" "),s("li",[t._v("log each field execution time")]),t._v(" "),s("li",[t._v("support "),s("a",{attrs:{href:"https://github.com/apollographql/apollo-tracing",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Tracing"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/apollographql/apollo-cache-control",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Caching"),s("OutboundLink")],1),t._v(" or anything similar")]),t._v(" "),s("li",[t._v("etc.")])]),t._v(" "),s("h2",{attrs:{id:"wrapper-types"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#wrapper-types"}},[t._v("#")]),t._v(" Wrapper types")]),t._v(" "),s("p",[t._v("There are 6 basic types of wrappers:")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("OverallWrapper")]),t._v(" to wrap the whole query processing")]),t._v(" "),s("li",[s("code",[t._v("ParsingWrapper")]),t._v(" to wrap the query parsing only")]),t._v(" "),s("li",[s("code",[t._v("ValidationWrapper")]),t._v(" to wrap the query validation only")]),t._v(" "),s("li",[s("code",[t._v("ExecutionWrapper")]),t._v(" to wrap the query execution only")]),t._v(" "),s("li",[s("code",[t._v("FieldWrapper")]),t._v(" to wrap each field execution")]),t._v(" "),s("li",[s("code",[t._v("IntrospectionWrapper")]),t._v(" to wrap the introspection query only")])]),t._v(" "),s("p",[t._v("Each one requires a function that takes a "),s("code",[t._v("ZIO")]),t._v(" or "),s("code",[t._v("ZQuery")]),t._v(" computation together with some contextual information (e.g. the query string) and should return another computation.")]),t._v(" "),s("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(" "),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(" wrapper "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" OverallWrapper"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Clock"),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("def")]),t._v(" wrap"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Clock"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n process"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLRequest "),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("R"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" GraphQLResponse"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CalibanError"),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 punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLRequest "),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("R"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" GraphQLResponse"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CalibanError"),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 operator"}},[t._v("=")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLRequest"),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 process"),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("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timeout"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" minute"),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("map"),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("getOrElse"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GraphQLResponse"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n NullValue"),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("ExecutionError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Query was interrupted after 1 minute:\\n${request.query}"')]),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 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("You can also combine wrappers using "),s("code",[t._v("|+|")]),t._v(" and create a wrapper that requires an effect to be run at each query using "),s("code",[t._v("EffectfulWrapper")]),t._v(".")]),t._v(" "),s("p",[t._v("To use your wrapper, call "),s("code",[t._v("GraphQL#withWrapper")]),t._v(" or its alias "),s("code",[t._v("@@")]),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("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 punctuation"}},[t._v(".")]),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(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("withWrapper"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("wrapper"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or")]),t._v("\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 punctuation"}},[t._v(".")]),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(" @@ wrapper\n")])])]),s("h2",{attrs:{id:"pre-defined-wrappers"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#pre-defined-wrappers"}},[t._v("#")]),t._v(" Pre-defined wrappers")]),t._v(" "),s("p",[t._v("Caliban comes with a few pre-made wrappers in "),s("code",[t._v("caliban.wrappers.Wrappers")]),t._v(":")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("maxDepth")]),t._v(" returns a wrapper that fails queries whose depth is higher than a given value")]),t._v(" "),s("li",[s("code",[t._v("maxFields")]),t._v(" returns a wrapper that fails queries whose number of fields is higher than a given value")]),t._v(" "),s("li",[s("code",[t._v("timeout")]),t._v(" returns a wrapper that fails queries taking more than a specified time")]),t._v(" "),s("li",[s("code",[t._v("printErrors")]),t._v(" returns a wrapper that prints errors")]),t._v(" "),s("li",[s("code",[t._v("printSlowQueries")]),t._v(" returns a wrapper that prints slow queries")]),t._v(" "),s("li",[s("code",[t._v("onSlowQueries")]),t._v(" returns a wrapper that can run a given function on slow queries")])]),t._v(" "),s("p",[t._v("In addition to those, Caliban also ships with some non-spec but standard wrappers")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("caliban.wrappers.ApolloTracing.apolloTracing")]),t._v(" returns a wrapper that adds tracing data into the "),s("code",[t._v("extensions")]),t._v(" field of each response following "),s("a",{attrs:{href:"https://github.com/apollographql/apollo-tracing",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Tracing"),s("OutboundLink")],1),t._v(" format.")]),t._v(" "),s("li",[s("code",[t._v("caliban.wrappers.ApolloCaching.apolloCaching")]),t._v(" returns a wrapper that adds caching hints to properly annotated fields using the "),s("a",{attrs:{href:"https://github.com/apollographql/apollo-cache-control",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Caching"),s("OutboundLink")],1),t._v(" format.")]),t._v(" "),s("li",[s("code",[t._v("caliban.wrappers.ApolloPersistedQueries.apolloPersistedQueries")]),t._v(" returns a wrapper that caches and retrieves query using a hash using the "),s("a",{attrs:{href:"https://github.com/apollographql/apollo-link-persisted-queries",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Persisted Queries"),s("OutboundLink")],1),t._v(" format.")])]),t._v(" "),s("p",[t._v("They can be used like this:")]),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(" api "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n graphQL"),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(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n maxDepth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("50")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n timeout"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v(" seconds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n printSlowQueries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("500")]),t._v(" millis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n apolloTracing @@\n apolloCaching\n")])])]),s("h2",{attrs:{id:"wrapping-the-interpreter"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#wrapping-the-interpreter"}},[t._v("#")]),t._v(" Wrapping the interpreter")]),t._v(" "),s("p",[t._v("All the wrappers mentioned above require that you don't modify the environment "),s("code",[t._v("R")]),t._v(" and the error type which is always a "),s("code",[t._v("CalibanError")]),t._v(". It is also possible to wrap your "),s("code",[t._v("GraphQLInterpreter")]),t._v(" by calling "),s("code",[t._v("wrapExecutionWith")]),t._v(" on it. This method takes in a function "),s("code",[t._v("f")]),t._v(" and returns a new "),s("code",[t._v("GraphQLInterpreter")]),t._v(" that will wrap the "),s("code",[t._v("execute")]),t._v(" method with this function "),s("code",[t._v("f")]),t._v(".")]),t._v(" "),s("p",[t._v("It is used internally to implement "),s("code",[t._v("mapError")]),t._v(" (customize errors) and "),s("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(" "),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(" i"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),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\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// change error type to String")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i2"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mapError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),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\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// provide the environment")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i3"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),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(" CalibanError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" i"),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("myEnv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// add a timeout on every query execution")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i4"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("with")]),t._v(" Clock"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),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 i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrapExecutionWith"),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("timeout"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("30")]),t._v(" seconds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),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("\n _"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getOrElse"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GraphQLResponse"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("NullValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Timeout!"')]),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(")")]),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("h2",{attrs:{id:"customizing-error-responses"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#customizing-error-responses"}},[t._v("#")]),t._v(" Customizing error responses")]),t._v(" "),s("p",[t._v("During various phases of executing a query, an error may occur. Caliban renders the different instances of "),s("code",[t._v("CalibanError")]),t._v(" to a GraphQL spec compliant response. As a user, you will most likely encounter "),s("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 "),s("code",[t._v("Throwable")]),t._v(".")]),t._v(" "),s("p",[t._v("For more meaningful error handling, GraphQL spec allows for an "),s("a",{attrs:{href:"http://spec.graphql.org/June2018/#example-fce18",target:"_blank",rel:"noopener noreferrer"}},[s("code",[t._v("extension")]),s("OutboundLink")],1),t._v(" object in the error response. This object may include, for instance, "),s("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 "),s("code",[t._v("mapError")]),t._v(" function on a "),s("code",[t._v("GraphQLInterpreter")]),t._v(". An example is provided below in which we map a custom domain error within an "),s("code",[t._v("ExecutionError")]),t._v(" to a meaningful error code.")]),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("sealed")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" ExampleAppEncodableError "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Throwable "),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(" errorCode"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v("\n"),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("object")]),t._v(" UnauthorizedError "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" ExampleAppEncodableError "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" errorCode"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"UNAUTHORIZED"')]),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("def")]),t._v(" withErrorCodeExtensions"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n interpreter"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),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(" CalibanError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),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(" CalibanError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" interpreter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mapError "),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(" err @ ExecutionError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("exampleError"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ExampleAppEncodableError"),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 punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),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("extensions "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),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 string"}},[t._v('"errorCode"')]),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("exampleError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("errorCode"),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(")")]),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("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ExecutionError "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),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("extensions "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),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 string"}},[t._v('"errorCode"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"EXECUTION_ERROR"')]),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(")")]),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("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ValidationError "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),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("extensions "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),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 string"}},[t._v('"errorCode"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"VALIDATION_ERROR"')]),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(")")]),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("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ParsingError "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),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("extensions "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),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 string"}},[t._v('"errorCode"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"PARSING_ERROR"')]),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(")")]),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("\n"),s("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([[15],{401:function(t,a,s){"use strict";s.r(a);var n=s(54),e=Object(n.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"middleware"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#middleware"}},[t._v("#")]),t._v(" Middleware")]),t._v(" "),s("p",[t._v("Caliban allows you to perform additional actions at various levels of a query processing, via the concept of "),s("code",[t._v("Wrapper")]),t._v(". Using wrappers, you can:")]),t._v(" "),s("ul",[s("li",[t._v("verify that a query doesn't reach some limit (e.g. depth, complexity)")]),t._v(" "),s("li",[t._v("modify a query before it's executed")]),t._v(" "),s("li",[t._v("add timeouts to queries or fields")]),t._v(" "),s("li",[t._v("log each field execution time")]),t._v(" "),s("li",[t._v("support "),s("a",{attrs:{href:"https://github.com/apollographql/apollo-tracing",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Tracing"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/apollographql/apollo-cache-control",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Caching"),s("OutboundLink")],1),t._v(" or anything similar")]),t._v(" "),s("li",[t._v("etc.")])]),t._v(" "),s("h2",{attrs:{id:"wrapper-types"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#wrapper-types"}},[t._v("#")]),t._v(" Wrapper types")]),t._v(" "),s("p",[t._v("There are 6 basic types of wrappers:")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("OverallWrapper")]),t._v(" to wrap the whole query processing")]),t._v(" "),s("li",[s("code",[t._v("ParsingWrapper")]),t._v(" to wrap the query parsing only")]),t._v(" "),s("li",[s("code",[t._v("ValidationWrapper")]),t._v(" to wrap the query validation only")]),t._v(" "),s("li",[s("code",[t._v("ExecutionWrapper")]),t._v(" to wrap the query execution only")]),t._v(" "),s("li",[s("code",[t._v("FieldWrapper")]),t._v(" to wrap each field execution")]),t._v(" "),s("li",[s("code",[t._v("IntrospectionWrapper")]),t._v(" to wrap the introspection query only")])]),t._v(" "),s("p",[t._v("Each one requires a function that takes a "),s("code",[t._v("ZIO")]),t._v(" or "),s("code",[t._v("ZQuery")]),t._v(" computation together with some contextual information (e.g. the query string) and should return another computation.")]),t._v(" "),s("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(" "),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(" wrapper "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" OverallWrapper"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Clock"),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("def")]),t._v(" wrap"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Clock"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n process"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLRequest "),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("R"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" GraphQLResponse"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CalibanError"),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 punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLRequest "),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("R"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" GraphQLResponse"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CalibanError"),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 operator"}},[t._v("=")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLRequest"),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 process"),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("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timeout"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" minute"),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("map"),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("getOrElse"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GraphQLResponse"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n NullValue"),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("ExecutionError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Query was interrupted after 1 minute:\\n${request.query}"')]),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 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("You can also combine wrappers using "),s("code",[t._v("|+|")]),t._v(" and create a wrapper that requires an effect to be run at each query using "),s("code",[t._v("EffectfulWrapper")]),t._v(".")]),t._v(" "),s("p",[t._v("To use your wrapper, call "),s("code",[t._v("GraphQL#withWrapper")]),t._v(" or its alias "),s("code",[t._v("@@")]),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("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 punctuation"}},[t._v(".")]),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(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("withWrapper"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("wrapper"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or")]),t._v("\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 punctuation"}},[t._v(".")]),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(" @@ wrapper\n")])])]),s("h2",{attrs:{id:"pre-defined-wrappers"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#pre-defined-wrappers"}},[t._v("#")]),t._v(" Pre-defined wrappers")]),t._v(" "),s("p",[t._v("Caliban comes with a few pre-made wrappers in "),s("code",[t._v("caliban.wrappers.Wrappers")]),t._v(":")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("maxDepth")]),t._v(" returns a wrapper that fails queries whose depth is higher than a given value")]),t._v(" "),s("li",[s("code",[t._v("maxFields")]),t._v(" returns a wrapper that fails queries whose number of fields is higher than a given value")]),t._v(" "),s("li",[s("code",[t._v("timeout")]),t._v(" returns a wrapper that fails queries taking more than a specified time")]),t._v(" "),s("li",[s("code",[t._v("printErrors")]),t._v(" returns a wrapper that prints errors")]),t._v(" "),s("li",[s("code",[t._v("printSlowQueries")]),t._v(" returns a wrapper that prints slow queries")]),t._v(" "),s("li",[s("code",[t._v("onSlowQueries")]),t._v(" returns a wrapper that can run a given function on slow queries")])]),t._v(" "),s("p",[t._v("In addition to those, Caliban also ships with some non-spec but standard wrappers")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("caliban.wrappers.ApolloTracing.apolloTracing")]),t._v(" returns a wrapper that adds tracing data into the "),s("code",[t._v("extensions")]),t._v(" field of each response following "),s("a",{attrs:{href:"https://github.com/apollographql/apollo-tracing",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Tracing"),s("OutboundLink")],1),t._v(" format.")]),t._v(" "),s("li",[s("code",[t._v("caliban.wrappers.ApolloCaching.apolloCaching")]),t._v(" returns a wrapper that adds caching hints to properly annotated fields using the "),s("a",{attrs:{href:"https://github.com/apollographql/apollo-cache-control",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Caching"),s("OutboundLink")],1),t._v(" format.")]),t._v(" "),s("li",[s("code",[t._v("caliban.wrappers.ApolloPersistedQueries.apolloPersistedQueries")]),t._v(" returns a wrapper that caches and retrieves query using a hash using the "),s("a",{attrs:{href:"https://github.com/apollographql/apollo-link-persisted-queries",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Persisted Queries"),s("OutboundLink")],1),t._v(" format.")])]),t._v(" "),s("p",[t._v("They can be used like this:")]),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(" api "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n graphQL"),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(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n maxDepth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("50")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n timeout"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v(" seconds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n printSlowQueries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("500")]),t._v(" millis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n apolloTracing @@\n apolloCaching\n")])])]),s("h2",{attrs:{id:"wrapping-the-interpreter"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#wrapping-the-interpreter"}},[t._v("#")]),t._v(" Wrapping the interpreter")]),t._v(" "),s("p",[t._v("All the wrappers mentioned above require that you don't modify the environment "),s("code",[t._v("R")]),t._v(" and the error type which is always a "),s("code",[t._v("CalibanError")]),t._v(". It is also possible to wrap your "),s("code",[t._v("GraphQLInterpreter")]),t._v(" by calling "),s("code",[t._v("wrapExecutionWith")]),t._v(" on it. This method takes in a function "),s("code",[t._v("f")]),t._v(" and returns a new "),s("code",[t._v("GraphQLInterpreter")]),t._v(" that will wrap the "),s("code",[t._v("execute")]),t._v(" method with this function "),s("code",[t._v("f")]),t._v(".")]),t._v(" "),s("p",[t._v("It is used internally to implement "),s("code",[t._v("mapError")]),t._v(" (customize errors) and "),s("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(" "),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(" i"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),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\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// change error type to String")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i2"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mapError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),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\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// provide the environment")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i3"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),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(" CalibanError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" i"),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("myEnv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// add a timeout on every query execution")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i4"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("with")]),t._v(" Clock"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),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 i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrapExecutionWith"),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("timeout"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("30")]),t._v(" seconds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),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("\n _"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getOrElse"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GraphQLResponse"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("NullValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Timeout!"')]),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(")")]),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("h2",{attrs:{id:"customizing-error-responses"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#customizing-error-responses"}},[t._v("#")]),t._v(" Customizing error responses")]),t._v(" "),s("p",[t._v("During various phases of executing a query, an error may occur. Caliban renders the different instances of "),s("code",[t._v("CalibanError")]),t._v(" to a GraphQL spec compliant response. As a user, you will most likely encounter "),s("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 "),s("code",[t._v("Throwable")]),t._v(".")]),t._v(" "),s("p",[t._v("For more meaningful error handling, GraphQL spec allows for an "),s("a",{attrs:{href:"http://spec.graphql.org/June2018/#example-fce18",target:"_blank",rel:"noopener noreferrer"}},[s("code",[t._v("extension")]),s("OutboundLink")],1),t._v(" object in the error response. This object may include, for instance, "),s("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 "),s("code",[t._v("mapError")]),t._v(" function on a "),s("code",[t._v("GraphQLInterpreter")]),t._v(". An example is provided below in which we map a custom domain error within an "),s("code",[t._v("ExecutionError")]),t._v(" to a meaningful error code.")]),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("sealed")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" ExampleAppEncodableError "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Throwable "),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(" errorCode"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v("\n"),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("object")]),t._v(" UnauthorizedError "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" ExampleAppEncodableError "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" errorCode"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"UNAUTHORIZED"')]),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("def")]),t._v(" withErrorCodeExtensions"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n interpreter"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),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(" CalibanError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),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(" CalibanError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" interpreter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mapError "),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(" err @ ExecutionError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("exampleError"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ExampleAppEncodableError"),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 punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),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("extensions "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),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 string"}},[t._v('"errorCode"')]),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("exampleError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("errorCode"),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(")")]),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("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ExecutionError "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),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("extensions "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),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 string"}},[t._v('"errorCode"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"EXECUTION_ERROR"')]),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(")")]),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("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ValidationError "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),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("extensions "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),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 string"}},[t._v('"errorCode"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"VALIDATION_ERROR"')]),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(")")]),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("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ParsingError "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),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("extensions "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),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 string"}},[t._v('"errorCode"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"PARSING_ERROR"')]),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(")")]),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("\n"),s("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/16.9e329d2b.js b/docs/assets/js/16.2d4ba3db.js similarity index 99% rename from docs/assets/js/16.9e329d2b.js rename to docs/assets/js/16.2d4ba3db.js index 24ffdde7ab..85122749f7 100644 --- a/docs/assets/js/16.9e329d2b.js +++ b/docs/assets/js/16.2d4ba3db.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[16],{389:function(t,a,s){"use strict";s.r(a);var e=s(46),n=Object(e.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"query-optimization"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#query-optimization"}},[t._v("#")]),t._v(" Query optimization")]),t._v(" "),s("p",[t._v("A GraphQL query may request multiple fields that are using the same resolver. It's not a problem if the resolver is a simple value, but it can be less than optimal when the resolver runs an effect (such as reading from a database).")]),t._v(" "),s("p",[t._v("We might want to:")]),t._v(" "),s("ul",[s("li",[s("strong",[t._v("cache")]),t._v(" identical queries (deduplication)")]),t._v(" "),s("li",[s("strong",[t._v("batch")]),t._v(" queries to the same source")])]),t._v(" "),s("p",[t._v("This is possible in Caliban using the "),s("a",{attrs:{href:"https://github.com/zio/zquery",target:"_blank",rel:"noopener noreferrer"}},[s("code",[t._v("ZQuery")]),s("OutboundLink")],1),t._v(" data type.")]),t._v(" "),s("p",[t._v("Additionally, one may want to perform optimizations based on the fields selected by the client.\nThis optimization can be achieved by field metadata from Caliban that can be referenced in your query classes.")]),t._v(" "),s("h2",{attrs:{id:"introducing-zquery"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#introducing-zquery"}},[t._v("#")]),t._v(" Introducing ZQuery")]),t._v(" "),s("p",[t._v("A "),s("code",[t._v("ZQuery[R, E, A]")]),t._v(" is a purely functional description of an effectual query that may contain requests to one or more data sources. Similarly to "),s("code",[t._v("ZIO[R, E, A]")]),t._v(", it requires an environment "),s("code",[t._v("R")]),t._v(", may fail with an "),s("code",[t._v("E")]),t._v(" or succeed with an "),s("code",[t._v("A")]),t._v(". All requests that do not need to be performed sequentially will automatically be batched, allowing for aggressive data source specific optimizations. Requests will also automatically be deduplicated and cached.")]),t._v(" "),s("p",[t._v("This allows for writing queries in a high level, compositional style, with confidence that they will automatically be optimized. For example, consider the following query from a user service.")]),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(" getAllUserIds"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ZQuery"),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 builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),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 operator"}},[t._v("=")]),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("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" getUserNameById"),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("Int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ZQuery"),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 builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),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\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 userIds "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" getAllUserIds\n userNames "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ZQuery"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("foreachPar"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("userIds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("getUserNameById"),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(" userNames\n")])])]),s("p",[t._v("This would normally require N + 1 queries, one for "),s("code",[t._v("getAllUserIds")]),t._v(" and one for each call to "),s("code",[t._v("getUserNameById")]),t._v(". In contrast, "),s("code",[t._v("ZQuery")]),t._v(" will automatically optimize this to two queries, one for "),s("code",[t._v("userIds")]),t._v(" and one for "),s("code",[t._v("userNames")]),t._v(", assuming an implementation of the user service that supports batching.")]),t._v(" "),s("h2",{attrs:{id:"building-a-datasource"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#building-a-datasource"}},[t._v("#")]),t._v(" Building a DataSource")]),t._v(" "),s("p",[t._v("To build a "),s("code",[t._v("ZQuery")]),t._v(" that executes a request, you first need to build a "),s("code",[t._v("DataSource")]),t._v(". A "),s("code",[t._v("DataSource[R, E, A]")]),t._v(" defines how to execute requests of type "),s("code",[t._v("A")]),t._v(" and it requires 2 things:")]),t._v(" "),s("ul",[s("li",[t._v("an "),s("code",[t._v("identifier")]),t._v(" that uniquely identifies the data source (requests from "),s("em",[t._v("different")]),t._v(" data sources will "),s("em",[t._v("not")]),t._v(" be batched together)")]),t._v(" "),s("li",[t._v("a effectful function "),s("code",[t._v("run")]),t._v(" from an "),s("code",[t._v("Iterable")]),t._v(" of requests to a "),s("code",[t._v("Map")]),t._v(" of requests and results")])]),t._v(" "),s("p",[t._v("Let's consider "),s("code",[t._v("getUserNameById")]),t._v(" from the previous example. We need to define a corresponding request type that extends "),s("code",[t._v("zquery.Request")]),t._v(" for a given response type:")]),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(" GetUserName"),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("Int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Throwable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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")])])]),s("p",[t._v("Now let's build the corresponding "),s("code",[t._v("DataSource")]),t._v(". We need to implement the following functions:")]),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(" UserDataSource "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" DataSource"),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(" GetUserName"),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("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" identifier"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),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("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" run"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("requests"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Iterable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("GetUserName"),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 operator"}},[t._v(":")]),t._v(" ZIO"),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(" Throwable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CompletedRequestMap"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),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("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v('We will use "UserDataSource" as our identifier. This name should not be reused for other data sources.')]),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("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" identifier"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"UserDataSource"')]),t._v("\n")])])]),s("p",[t._v("We will define two different behaviors depending on whether we receive a single request or multiple requests at once.\nFor each request, we need to insert into the result map a value of type "),s("code",[t._v("Either")]),t._v(" ("),s("code",[t._v("Left")]),t._v(" for an error and "),s("code",[t._v("Right")]),t._v(" for a success).")]),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("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" run"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("requests"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Iterable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("GetUserName"),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 operator"}},[t._v(":")]),t._v(" ZIO"),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 builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CompletedRequestMap"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[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("val")]),t._v(" resultMap "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" CompletedRequestMap"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("empty\n requests"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toList "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),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(" request "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("::")]),t._v(" Nil "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// get user by ID e.g. SELECT name FROM users WHERE id = $id")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" result"),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(" "),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 result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("either"),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("resultMap"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("insert"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),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 keyword"}},[t._v("case")]),t._v(" batch "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// get multiple users at once e.g. SELECT id, name FROM users WHERE id IN ($ids)")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" result"),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("List"),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 builtin"}},[t._v("Int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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 punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),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 result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fold"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n err "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" requests"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("foldLeft"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultMap"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),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(" req"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" map"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("insert"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("req"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Left"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),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 punctuation"}},[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("foldLeft"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultMap"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),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(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" name"),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(" map"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("insert"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GetUserName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),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("Right"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),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 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 to build a "),s("code",[t._v("ZQuery")]),t._v(" from it, we can use "),s("code",[t._v("ZQuery.fromRequest")]),t._v(" and just pass the request and the data source:")]),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("def")]),t._v(" getUserNameById"),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("Int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ZQuery"),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(" Throwable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n ZQuery"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromRequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GetUserName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),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("UserDataSource"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("To run a "),s("code",[t._v("ZQuery")]),t._v(", simply use "),s("code",[t._v("ZQuery#run")]),t._v(" which will return a "),s("code",[t._v("ZIO[R, E, A]")]),t._v(".")]),t._v(" "),s("h2",{attrs:{id:"zquery-constructors-and-operators"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#zquery-constructors-and-operators"}},[t._v("#")]),t._v(" ZQuery constructors and operators")]),t._v(" "),s("p",[t._v("There are several ways to create a "),s("code",[t._v("ZQuery")]),t._v(". We've seen "),s("code",[t._v("ZQuery.fromRequest")]),t._v(", but you can also:")]),t._v(" "),s("ul",[s("li",[t._v("create from a pure value with "),s("code",[t._v("ZQuery.succeed")])]),t._v(" "),s("li",[t._v("create from an effect value with "),s("code",[t._v("ZQuery.fromEffect")])]),t._v(" "),s("li",[t._v("create from multiple queries with "),s("code",[t._v("ZQuery.collectAllPar")]),t._v(" and "),s("code",[t._v("ZQuery.foreachPar")]),t._v(" and their sequential equivalents "),s("code",[t._v("ZQuery.collectAll")]),t._v(" and "),s("code",[t._v("ZQuery.foreach")])])]),t._v(" "),s("p",[t._v("If you have a "),s("code",[t._v("ZQuery")]),t._v(" object, you can use:")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("map")]),t._v(" and "),s("code",[t._v("mapError")]),t._v(" to modify the returned result or error")]),t._v(" "),s("li",[s("code",[t._v("flatMap")]),t._v(" or "),s("code",[t._v("zip")]),t._v(" to combine it with other "),s("code",[t._v("ZQuery")]),t._v(" objects")]),t._v(" "),s("li",[s("code",[t._v("provide")]),t._v(" and "),s("code",[t._v("provideSome")]),t._v(" to eliminate some of the "),s("code",[t._v("R")]),t._v(" requirements")])]),t._v(" "),s("p",[t._v("There are several ways to run a "),s("code",[t._v("ZQuery")]),t._v(":")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("runCache")]),t._v(' runs the query using a given pre-populated cache. This can be useful for deterministically "replaying" a query without executing any new requests.')]),t._v(" "),s("li",[s("code",[t._v("runLog")]),t._v(" runs the query and returns its result along with the cache containing a complete log of all requests executed and their results. This can be useful for logging or analysis of query execution.")]),t._v(" "),s("li",[s("code",[t._v("run")]),t._v(" runs the query and returns its result.")])]),t._v(" "),s("h2",{attrs:{id:"using-zquery-with-caliban"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#using-zquery-with-caliban"}},[t._v("#")]),t._v(" Using ZQuery with Caliban")]),t._v(" "),s("p",[t._v("To use "),s("code",[t._v("ZQuery")]),t._v(" with Caliban, you can simply include fields of type "),s("code",[t._v("ZQuery")]),t._v(" in your API definition.")]),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(" Queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n users"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ZQuery"),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 builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("User"),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("\n user"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UserArgs "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZQuery"),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 builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" User"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("During the query execution, Caliban will merge all the requested fields that return a "),s("code",[t._v("ZQuery")]),t._v(" into a single "),s("code",[t._v("ZQuery")]),t._v(" and run it, so that all the possible optimizations are applied.")]),t._v(" "),s("p",[t._v("The "),s("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples",target:"_blank",rel:"noopener noreferrer"}},[t._v("examples"),s("OutboundLink")],1),t._v(" project provides 2 versions of the problem described in "),s("a",{attrs:{href:"https://blog.apollographql.com/optimizing-your-graphql-request-waterfalls-7c3f3360b051",target:"_blank",rel:"noopener noreferrer"}},[t._v("this article about GraphQL query optimization"),s("OutboundLink")],1),t._v(":")]),t._v(" "),s("ul",[s("li",[t._v("a "),s("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/optimizations/NaiveTest.scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("naive"),s("OutboundLink")],1),t._v(" version where fields are just returning "),s("code",[t._v("IO")]),t._v(", resulting in 47 requests")]),t._v(" "),s("li",[t._v("an "),s("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/optimizations/OptimizedTest.scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("optimized"),s("OutboundLink")],1),t._v(" version where fields are returning "),s("code",[t._v("ZQuery")]),t._v(", resulting in 8 requests only")])]),t._v(" "),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),s("p",[t._v("When all your effects are wrapped with "),s("code",[t._v("ZQuery.fromRequest")]),t._v(", it is recommended to use "),s("code",[t._v("queryExecution = QueryExecution.Batched")]),t._v(" instead of the default "),s("code",[t._v("QueryExecution.Parallel")]),t._v(".\nDoing so will provide better performance as it will avoid forking unnecessary fibers.\nThis setting is available in "),s("code",[t._v("executeRequest")]),t._v(" as well as all the adapters.")])]),t._v(" "),s("h2",{attrs:{id:"using-field-metadata"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#using-field-metadata"}},[t._v("#")]),t._v(" Using field metadata")]),t._v(" "),s("p",[t._v("To reference field metadata in your queries you can simply use a function that takes the "),s("code",[t._v("caliban.execution.Field")]),t._v(" type in your queries.")]),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(" User"),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(" expensiveOperation"),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"),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 user"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Field "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" User\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("You can also do this with functions that take inputs.")]),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(" UserInput"),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("\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(" User"),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(" expensiveOperation"),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"),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 user"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Field "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("UserInput "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" User"),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("In the resulting GraphQL Schema the "),s("em",[t._v("Field")]),t._v(" will be ignored giving you the equivalent of just the returned type of the function.")]),t._v(" "),s("p",[t._v("The implementation of the function can then take the field metadata into account for optimization.\nFor instance one could modify a database query to only select certain columns or do joins to additional tables depending on what the client requests.")]),t._v(" "),s("p",[t._v("For example:")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[t._v("Queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v(" "),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(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[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("if")]),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("fields"),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("_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("contains"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"expensiveOperation"')]),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 punctuation"}},[t._v("{")]),t._v("\n expensiveUserRequest"),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 punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n efficientUserRequest"),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 punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("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([[16],{400:function(t,a,s){"use strict";s.r(a);var e=s(54),n=Object(e.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"query-optimization"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#query-optimization"}},[t._v("#")]),t._v(" Query optimization")]),t._v(" "),s("p",[t._v("A GraphQL query may request multiple fields that are using the same resolver. It's not a problem if the resolver is a simple value, but it can be less than optimal when the resolver runs an effect (such as reading from a database).")]),t._v(" "),s("p",[t._v("We might want to:")]),t._v(" "),s("ul",[s("li",[s("strong",[t._v("cache")]),t._v(" identical queries (deduplication)")]),t._v(" "),s("li",[s("strong",[t._v("batch")]),t._v(" queries to the same source")])]),t._v(" "),s("p",[t._v("This is possible in Caliban using the "),s("a",{attrs:{href:"https://github.com/zio/zquery",target:"_blank",rel:"noopener noreferrer"}},[s("code",[t._v("ZQuery")]),s("OutboundLink")],1),t._v(" data type.")]),t._v(" "),s("p",[t._v("Additionally, one may want to perform optimizations based on the fields selected by the client.\nThis optimization can be achieved by field metadata from Caliban that can be referenced in your query classes.")]),t._v(" "),s("h2",{attrs:{id:"introducing-zquery"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#introducing-zquery"}},[t._v("#")]),t._v(" Introducing ZQuery")]),t._v(" "),s("p",[t._v("A "),s("code",[t._v("ZQuery[R, E, A]")]),t._v(" is a purely functional description of an effectual query that may contain requests to one or more data sources. Similarly to "),s("code",[t._v("ZIO[R, E, A]")]),t._v(", it requires an environment "),s("code",[t._v("R")]),t._v(", may fail with an "),s("code",[t._v("E")]),t._v(" or succeed with an "),s("code",[t._v("A")]),t._v(". All requests that do not need to be performed sequentially will automatically be batched, allowing for aggressive data source specific optimizations. Requests will also automatically be deduplicated and cached.")]),t._v(" "),s("p",[t._v("This allows for writing queries in a high level, compositional style, with confidence that they will automatically be optimized. For example, consider the following query from a user service.")]),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(" getAllUserIds"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ZQuery"),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 builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),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 operator"}},[t._v("=")]),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("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" getUserNameById"),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("Int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ZQuery"),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 builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),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\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 userIds "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" getAllUserIds\n userNames "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ZQuery"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("foreachPar"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("userIds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("getUserNameById"),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(" userNames\n")])])]),s("p",[t._v("This would normally require N + 1 queries, one for "),s("code",[t._v("getAllUserIds")]),t._v(" and one for each call to "),s("code",[t._v("getUserNameById")]),t._v(". In contrast, "),s("code",[t._v("ZQuery")]),t._v(" will automatically optimize this to two queries, one for "),s("code",[t._v("userIds")]),t._v(" and one for "),s("code",[t._v("userNames")]),t._v(", assuming an implementation of the user service that supports batching.")]),t._v(" "),s("h2",{attrs:{id:"building-a-datasource"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#building-a-datasource"}},[t._v("#")]),t._v(" Building a DataSource")]),t._v(" "),s("p",[t._v("To build a "),s("code",[t._v("ZQuery")]),t._v(" that executes a request, you first need to build a "),s("code",[t._v("DataSource")]),t._v(". A "),s("code",[t._v("DataSource[R, E, A]")]),t._v(" defines how to execute requests of type "),s("code",[t._v("A")]),t._v(" and it requires 2 things:")]),t._v(" "),s("ul",[s("li",[t._v("an "),s("code",[t._v("identifier")]),t._v(" that uniquely identifies the data source (requests from "),s("em",[t._v("different")]),t._v(" data sources will "),s("em",[t._v("not")]),t._v(" be batched together)")]),t._v(" "),s("li",[t._v("a effectful function "),s("code",[t._v("run")]),t._v(" from an "),s("code",[t._v("Iterable")]),t._v(" of requests to a "),s("code",[t._v("Map")]),t._v(" of requests and results")])]),t._v(" "),s("p",[t._v("Let's consider "),s("code",[t._v("getUserNameById")]),t._v(" from the previous example. We need to define a corresponding request type that extends "),s("code",[t._v("zquery.Request")]),t._v(" for a given response type:")]),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(" GetUserName"),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("Int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Throwable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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")])])]),s("p",[t._v("Now let's build the corresponding "),s("code",[t._v("DataSource")]),t._v(". We need to implement the following functions:")]),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(" UserDataSource "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" DataSource"),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(" GetUserName"),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("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" identifier"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),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("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" run"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("requests"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Iterable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("GetUserName"),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 operator"}},[t._v(":")]),t._v(" ZIO"),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(" Throwable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CompletedRequestMap"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),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("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v('We will use "UserDataSource" as our identifier. This name should not be reused for other data sources.')]),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("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" identifier"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"UserDataSource"')]),t._v("\n")])])]),s("p",[t._v("We will define two different behaviors depending on whether we receive a single request or multiple requests at once.\nFor each request, we need to insert into the result map a value of type "),s("code",[t._v("Either")]),t._v(" ("),s("code",[t._v("Left")]),t._v(" for an error and "),s("code",[t._v("Right")]),t._v(" for a success).")]),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("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" run"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("requests"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Iterable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("GetUserName"),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 operator"}},[t._v(":")]),t._v(" ZIO"),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 builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CompletedRequestMap"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[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("val")]),t._v(" resultMap "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" CompletedRequestMap"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("empty\n requests"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toList "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),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(" request "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("::")]),t._v(" Nil "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// get user by ID e.g. SELECT name FROM users WHERE id = $id")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" result"),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(" "),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 result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("either"),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("resultMap"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("insert"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),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 keyword"}},[t._v("case")]),t._v(" batch "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// get multiple users at once e.g. SELECT id, name FROM users WHERE id IN ($ids)")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" result"),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("List"),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 builtin"}},[t._v("Int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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 punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),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 result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fold"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n err "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" requests"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("foldLeft"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultMap"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),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(" req"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" map"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("insert"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("req"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Left"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),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 punctuation"}},[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("foldLeft"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultMap"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),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(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" name"),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(" map"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("insert"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GetUserName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),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("Right"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),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 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 to build a "),s("code",[t._v("ZQuery")]),t._v(" from it, we can use "),s("code",[t._v("ZQuery.fromRequest")]),t._v(" and just pass the request and the data source:")]),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("def")]),t._v(" getUserNameById"),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("Int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ZQuery"),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(" Throwable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n ZQuery"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromRequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GetUserName"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),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("UserDataSource"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("To run a "),s("code",[t._v("ZQuery")]),t._v(", simply use "),s("code",[t._v("ZQuery#run")]),t._v(" which will return a "),s("code",[t._v("ZIO[R, E, A]")]),t._v(".")]),t._v(" "),s("h2",{attrs:{id:"zquery-constructors-and-operators"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#zquery-constructors-and-operators"}},[t._v("#")]),t._v(" ZQuery constructors and operators")]),t._v(" "),s("p",[t._v("There are several ways to create a "),s("code",[t._v("ZQuery")]),t._v(". We've seen "),s("code",[t._v("ZQuery.fromRequest")]),t._v(", but you can also:")]),t._v(" "),s("ul",[s("li",[t._v("create from a pure value with "),s("code",[t._v("ZQuery.succeed")])]),t._v(" "),s("li",[t._v("create from an effect value with "),s("code",[t._v("ZQuery.fromEffect")])]),t._v(" "),s("li",[t._v("create from multiple queries with "),s("code",[t._v("ZQuery.collectAllPar")]),t._v(" and "),s("code",[t._v("ZQuery.foreachPar")]),t._v(" and their sequential equivalents "),s("code",[t._v("ZQuery.collectAll")]),t._v(" and "),s("code",[t._v("ZQuery.foreach")])])]),t._v(" "),s("p",[t._v("If you have a "),s("code",[t._v("ZQuery")]),t._v(" object, you can use:")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("map")]),t._v(" and "),s("code",[t._v("mapError")]),t._v(" to modify the returned result or error")]),t._v(" "),s("li",[s("code",[t._v("flatMap")]),t._v(" or "),s("code",[t._v("zip")]),t._v(" to combine it with other "),s("code",[t._v("ZQuery")]),t._v(" objects")]),t._v(" "),s("li",[s("code",[t._v("provide")]),t._v(" and "),s("code",[t._v("provideSome")]),t._v(" to eliminate some of the "),s("code",[t._v("R")]),t._v(" requirements")])]),t._v(" "),s("p",[t._v("There are several ways to run a "),s("code",[t._v("ZQuery")]),t._v(":")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("runCache")]),t._v(' runs the query using a given pre-populated cache. This can be useful for deterministically "replaying" a query without executing any new requests.')]),t._v(" "),s("li",[s("code",[t._v("runLog")]),t._v(" runs the query and returns its result along with the cache containing a complete log of all requests executed and their results. This can be useful for logging or analysis of query execution.")]),t._v(" "),s("li",[s("code",[t._v("run")]),t._v(" runs the query and returns its result.")])]),t._v(" "),s("h2",{attrs:{id:"using-zquery-with-caliban"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#using-zquery-with-caliban"}},[t._v("#")]),t._v(" Using ZQuery with Caliban")]),t._v(" "),s("p",[t._v("To use "),s("code",[t._v("ZQuery")]),t._v(" with Caliban, you can simply include fields of type "),s("code",[t._v("ZQuery")]),t._v(" in your API definition.")]),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(" Queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n users"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ZQuery"),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 builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("User"),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("\n user"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UserArgs "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZQuery"),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 builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" User"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("During the query execution, Caliban will merge all the requested fields that return a "),s("code",[t._v("ZQuery")]),t._v(" into a single "),s("code",[t._v("ZQuery")]),t._v(" and run it, so that all the possible optimizations are applied.")]),t._v(" "),s("p",[t._v("The "),s("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples",target:"_blank",rel:"noopener noreferrer"}},[t._v("examples"),s("OutboundLink")],1),t._v(" project provides 2 versions of the problem described in "),s("a",{attrs:{href:"https://blog.apollographql.com/optimizing-your-graphql-request-waterfalls-7c3f3360b051",target:"_blank",rel:"noopener noreferrer"}},[t._v("this article about GraphQL query optimization"),s("OutboundLink")],1),t._v(":")]),t._v(" "),s("ul",[s("li",[t._v("a "),s("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/optimizations/NaiveTest.scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("naive"),s("OutboundLink")],1),t._v(" version where fields are just returning "),s("code",[t._v("IO")]),t._v(", resulting in 47 requests")]),t._v(" "),s("li",[t._v("an "),s("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/optimizations/OptimizedTest.scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("optimized"),s("OutboundLink")],1),t._v(" version where fields are returning "),s("code",[t._v("ZQuery")]),t._v(", resulting in 8 requests only")])]),t._v(" "),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),s("p",[t._v("When all your effects are wrapped with "),s("code",[t._v("ZQuery.fromRequest")]),t._v(", it is recommended to use "),s("code",[t._v("queryExecution = QueryExecution.Batched")]),t._v(" instead of the default "),s("code",[t._v("QueryExecution.Parallel")]),t._v(".\nDoing so will provide better performance as it will avoid forking unnecessary fibers.\nThis setting is available in "),s("code",[t._v("executeRequest")]),t._v(" as well as all the adapters.")])]),t._v(" "),s("h2",{attrs:{id:"using-field-metadata"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#using-field-metadata"}},[t._v("#")]),t._v(" Using field metadata")]),t._v(" "),s("p",[t._v("To reference field metadata in your queries you can simply use a function that takes the "),s("code",[t._v("caliban.execution.Field")]),t._v(" type in your queries.")]),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(" User"),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(" expensiveOperation"),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"),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 user"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Field "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" User\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("You can also do this with functions that take inputs.")]),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(" UserInput"),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("\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(" User"),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(" expensiveOperation"),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"),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 user"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Field "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("UserInput "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" User"),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("In the resulting GraphQL Schema the "),s("em",[t._v("Field")]),t._v(" will be ignored giving you the equivalent of just the returned type of the function.")]),t._v(" "),s("p",[t._v("The implementation of the function can then take the field metadata into account for optimization.\nFor instance one could modify a database query to only select certain columns or do joins to additional tables depending on what the client requests.")]),t._v(" "),s("p",[t._v("For example:")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[t._v("Queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v(" "),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(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[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("if")]),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("fields"),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("_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("contains"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"expensiveOperation"')]),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 punctuation"}},[t._v("{")]),t._v("\n expensiveUserRequest"),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 punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n efficientUserRequest"),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 punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("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/17.df959ed2.js b/docs/assets/js/17.df959ed2.js deleted file mode 100644 index bb5608ed0c..0000000000 --- a/docs/assets/js/17.df959ed2.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[17],{390:function(t,a,s){"use strict";s.r(a);var e=s(46),n=Object(e.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"schemas"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#schemas"}},[t._v("#")]),t._v(" Schemas")]),t._v(" "),s("p",[t._v("A GraphQL schema will be derived automatically at compile-time (no reflection) from the types present in your resolver.\nThe table below shows how common Scala types are converted to GraphQL types.")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Scala Type")]),t._v(" "),s("th",[t._v("GraphQL Type")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[t._v("Boolean")]),t._v(" "),s("td",[t._v("Boolean")])]),t._v(" "),s("tr",[s("td",[t._v("Int")]),t._v(" "),s("td",[t._v("Int")])]),t._v(" "),s("tr",[s("td",[t._v("Float")]),t._v(" "),s("td",[t._v("Float")])]),t._v(" "),s("tr",[s("td",[t._v("Double")]),t._v(" "),s("td",[t._v("Float")])]),t._v(" "),s("tr",[s("td",[t._v("String")]),t._v(" "),s("td",[t._v("String")])]),t._v(" "),s("tr",[s("td",[t._v("java.util.UUID")]),t._v(" "),s("td",[t._v("ID")])]),t._v(" "),s("tr",[s("td",[t._v("Unit")]),t._v(" "),s("td",[t._v("Unit (custom scalar)")])]),t._v(" "),s("tr",[s("td",[t._v("Long")]),t._v(" "),s("td",[t._v("Long (custom scalar)")])]),t._v(" "),s("tr",[s("td",[t._v("BigInt")]),t._v(" "),s("td",[t._v("BigInt (custom scalar)")])]),t._v(" "),s("tr",[s("td",[t._v("BigDecimal")]),t._v(" "),s("td",[t._v("BigDecimal (custom scalar)")])]),t._v(" "),s("tr",[s("td",[t._v("java.time.Instant")]),t._v(" "),s("td",[t._v("Instant (custom scalar)")])]),t._v(" "),s("tr",[s("td",[t._v("java.time.LocalDate")]),t._v(" "),s("td",[t._v("LocalDate (custom scalar)")])]),t._v(" "),s("tr",[s("td",[t._v("java.time.LocalTime")]),t._v(" "),s("td",[t._v("LocalTime (custom scalar)")])]),t._v(" "),s("tr",[s("td",[t._v("java.time.LocalDateTime")]),t._v(" "),s("td",[t._v("LocalDateTime (custom scalar)")])]),t._v(" "),s("tr",[s("td",[t._v("java.time.OffsetDateTime")]),t._v(" "),s("td",[t._v("OffsetDateTime (custom scalar)")])]),t._v(" "),s("tr",[s("td",[t._v("java.time.ZonedDateTime")]),t._v(" "),s("td",[t._v("ZonedDateTime (custom scalar)")])]),t._v(" "),s("tr",[s("td",[t._v("Case Class")]),t._v(" "),s("td",[t._v("Object")])]),t._v(" "),s("tr",[s("td",[t._v("Sealed Trait")]),t._v(" "),s("td",[t._v("Enum or Union")])]),t._v(" "),s("tr",[s("td",[t._v("Option[A]")]),t._v(" "),s("td",[t._v("Nullable A")])]),t._v(" "),s("tr",[s("td",[t._v("List[A]")]),t._v(" "),s("td",[t._v("List of A")])]),t._v(" "),s("tr",[s("td",[t._v("Set[A]")]),t._v(" "),s("td",[t._v("List of A")])]),t._v(" "),s("tr",[s("td",[t._v("Seq[A]")]),t._v(" "),s("td",[t._v("List of A")])]),t._v(" "),s("tr",[s("td",[t._v("Vector[A]")]),t._v(" "),s("td",[t._v("List of A")])]),t._v(" "),s("tr",[s("td",[t._v("A => B")]),t._v(" "),s("td",[t._v("A and B")])]),t._v(" "),s("tr",[s("td",[t._v("(A, B)")]),t._v(" "),s("td",[t._v("Object with 2 fields "),s("code",[t._v("_1")]),t._v(" and "),s("code",[t._v("_2")])])]),t._v(" "),s("tr",[s("td",[t._v("Either[A, B]")]),t._v(" "),s("td",[t._v("Object with 2 nullable fields "),s("code",[t._v("left")]),t._v(" and "),s("code",[t._v("right")])])]),t._v(" "),s("tr",[s("td",[t._v("Map[A, B]")]),t._v(" "),s("td",[t._v("List of Object with 2 fields "),s("code",[t._v("key")]),t._v(" and "),s("code",[t._v("value")])])]),t._v(" "),s("tr",[s("td",[t._v("ZIO[R, Nothing, A]")]),t._v(" "),s("td",[t._v("A")])]),t._v(" "),s("tr",[s("td",[t._v("ZIO[R, Throwable, A]")]),t._v(" "),s("td",[t._v("Nullable A")])]),t._v(" "),s("tr",[s("td",[t._v("Future[A]")]),t._v(" "),s("td",[t._v("Nullable A")])]),t._v(" "),s("tr",[s("td",[t._v("ZStream[R, Throwable, A]")]),t._v(" "),s("td",[t._v("A (subscription) or List of A (query, mutation)")])]),t._v(" "),s("tr",[s("td",[t._v("Json (from "),s("a",{attrs:{href:"https://github.com/circe/circe",target:"_blank",rel:"noopener noreferrer"}},[t._v("Circe"),s("OutboundLink")],1),t._v(")")]),t._v(" "),s("td",[t._v("Json (custom scalar, need "),s("code",[t._v("import caliban.interop.circe.json._")]),t._v(")")])]),t._v(" "),s("tr",[s("td",[t._v("Json (from "),s("a",{attrs:{href:"https://github.com/playframework/play-json",target:"_blank",rel:"noopener noreferrer"}},[t._v("play-json"),s("OutboundLink")],1),t._v(")")]),t._v(" "),s("td",[t._v("Json (custom scalar, need "),s("code",[t._v("import caliban.interop.play.json._")]),t._v(")")])])])]),t._v(" "),s("p",[t._v("See the "),s("a",{attrs:{href:"#custom-types"}},[t._v("Custom Types")]),t._v(" section to find out how to support your own types.")]),t._v(" "),s("p",[t._v("If you want Caliban to support other standard types, feel free to "),s("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/issues",target:"_blank",rel:"noopener noreferrer"}},[t._v("file an issue"),s("OutboundLink")],1),t._v(" or even a PR.")]),t._v(" "),s("div",{staticClass:"custom-block warning"},[s("p",{staticClass:"custom-block-title"},[t._v("Schema derivation issues")]),t._v(" "),s("p",[t._v("The schema derivation sometimes has some trouble generating schemas with a lot of nested types, or types reused in multiple places.\nTo deal with this, you can declare schemas for your case classes and sealed traits explicitly:")]),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(" roleSchema "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Role"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),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(" characterSchema "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n")])])]),s("p",[t._v("Make sure those implicits are in scope when you call "),s("code",[t._v("graphQL(...)")]),t._v(". This will make derivation's job easier by pre-generating schemas for those classes and re-using them when needed.\nThis will also improve compilation times and generate less bytecode.")]),t._v(" "),s("p",[t._v("In Scala 2, if the derivation fails and you're not sure why, you can also call Magnolia's macro directly by using "),s("code",[t._v("genMacro")]),t._v(".\nThe compilation will return better error messages in case something is missing:")]),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(" characterSchema "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("genMacro"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema\n")])])]),s("p",[t._v("In Scala 3, derivation doesn't support value classes, opaque types and nested sealed traits.")])]),t._v(" "),s("h2",{attrs:{id:"enums-unions-interfaces"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#enums-unions-interfaces"}},[t._v("#")]),t._v(" Enums, unions, interfaces")]),t._v(" "),s("p",[t._v("A sealed trait will be converted to a different GraphQL type depending on its content:")]),t._v(" "),s("ul",[s("li",[t._v("a sealed trait with only case objects will be converted to an "),s("code",[t._v("ENUM")])]),t._v(" "),s("li",[t._v("a sealed trait with only case classes will be converted to a "),s("code",[t._v("UNION")])])]),t._v(" "),s("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 '),s("code",[t._v("_")]),t._v(" which is not queryable.")]),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("sealed")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" ORIGIN\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" ORIGIN "),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("object")]),t._v(" EARTH "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" ORIGIN\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" MARS "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" ORIGIN\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" BELT "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" ORIGIN\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("The snippet above will produce the following GraphQL type:")]),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("enum")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("BELT")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("EARTH")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("MARS")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("Here's an example of union:")]),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("sealed")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Role\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Role "),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(" Captain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("shipName"),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(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\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(" Engineer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("specialty"),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(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Mechanic "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("The snippet above will produce the following GraphQL type:")]),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("union")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Role")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("Captain")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("Engineer")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("Mechanic")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Captain")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("shipName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token operator"}},[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("type")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Engineer")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("specialty")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token operator"}},[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("type")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mechanic")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("_")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("Boolean")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("If your type needs to be shared between multiple unions you can use the "),s("code",[t._v("@GQLValueType")]),t._v(" annotation to have caliban\nproxy to another type beyond the sealed trait.")]),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(" Pilot"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("callSign"),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("sealed")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Role\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Role "),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(" Captain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("shipName"),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(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\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(" Engineer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("specialty"),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(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n \n "),s("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLValueType")]),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(" Proxy"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("pilot"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Pilot"),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("This will produce the following GraphQL Types:")]),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("union")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Role")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("Captain")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("Engineer")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("Pilot")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Captain")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("shipName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token operator"}},[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("type")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Engineer")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("specialty")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token operator"}},[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("type")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Pilot")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("callSign")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("If you prefer an "),s("code",[t._v("Interface")]),t._v(" instead of a "),s("code",[t._v("Union")]),t._v(" type, add the "),s("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(" "),s("p",[t._v("If you prefer to have a "),s("code",[t._v("Union")]),t._v(" type instead of an "),s("code",[t._v("Enum")]),t._v(", even when the sealed trait contains only objects, add the "),s("code",[t._v("@GQLUnion")]),t._v(" annotation.")]),t._v(" "),s("h2",{attrs:{id:"arguments"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#arguments"}},[t._v("#")]),t._v(" Arguments")]),t._v(" "),s("p",[t._v("To declare a field that take arguments, create a dedicated case class representing the arguments and make the field a "),s("em",[t._v("function")]),t._v(" from this class to the result type.")]),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(" FilterArgs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("origin"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Origin"),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 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("characters"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FilterArgs "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("The snippet above will produce the following GraphQL type:")]),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("type")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Queries")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("characters")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("origin")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),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 punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("Caliban provides auto-derivation for common types such as "),s("code",[t._v("Int")]),t._v(", "),s("code",[t._v("String")]),t._v(", "),s("code",[t._v("List")]),t._v(", "),s("code",[t._v("Option")]),t._v(", etc. but you can also support your own types by providing an implicit instance of "),s("code",[t._v("caliban.schema.ArgBuilder")]),t._v(".")]),t._v(" "),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),s("p",[t._v("There is no "),s("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(" "),s("h2",{attrs:{id:"effects"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#effects"}},[t._v("#")]),t._v(" Effects")]),t._v(" "),s("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(" "),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(" Queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),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("List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),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("\n character"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CharacterName "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" RIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Console"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Character"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("If you don't use ZIO environment ("),s("code",[t._v("R")]),t._v(" = "),s("code",[t._v("Any")]),t._v("), there is nothing special to do to get it working.")]),t._v(" "),s("p",[t._v("If you require a ZIO environment, you will need to have the content of "),s("code",[t._v("caliban.schema.GenericSchema[R]")]),t._v(" for your custom "),s("code",[t._v("R")]),t._v(" in scope when you call "),s("code",[t._v("graphQL(...)")]),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("object")]),t._v(" schema "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" GenericSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),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("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n")])])]),s("p",[t._v("Note: If you ever need to declare schemas explicitly (by calling "),s("code",[t._v("gen")]),t._v(" directly, as explained above), and you require a ZIO environment (explained in this section),\nthen you must use the "),s("code",[t._v("gen")]),t._v(" from this "),s("code",[t._v("object schema")]),t._v(". If you call "),s("code",[t._v("gen")]),t._v(" to derive schemas in the same module and you "),s("code",[t._v("import schema._")]),t._v(" at the top of this module,\nyou'd be fine. However, if you derive schemas in a separate module, then make sure you import this schema object in that module so that you'll be using the "),s("code",[t._v("gen")]),t._v(" from the "),s("code",[t._v("schema")]),t._v(" object.")]),t._v(" "),s("h2",{attrs:{id:"annotations"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#annotations"}},[t._v("#")]),t._v(" Annotations")]),t._v(" "),s("p",[t._v("Caliban supports a few annotations to enrich data types:")]),t._v(" "),s("ul",[s("li",[s("code",[t._v('@GQLName("name")')]),t._v(" allows you to specify a different name for a data type or a field.")]),t._v(" "),s("li",[s("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 "),s("code",[t._v("Input")]),t._v(" is appended to the type name).")]),t._v(" "),s("li",[s("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(" "),s("li",[s("code",[t._v('@GQLDeprecated("reason")')]),t._v(" allows deprecating a field or an enum value.")]),t._v(" "),s("li",[s("code",[t._v("@GQLInterface")]),t._v(" to force a sealed trait generating an interface instead of a union.")]),t._v(" "),s("li",[s("code",[t._v("@GQLDirective(directive: Directive)")]),t._v(" to add a directive to a field or type.")]),t._v(" "),s("li",[s("code",[t._v("@GQLValueType")]),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.")]),t._v(" "),s("li",[s("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(" "),s("h2",{attrs:{id:"java-8-time-types"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#java-8-time-types"}},[t._v("#")]),t._v(" Java 8 Time types")]),t._v(" "),s("p",[t._v("Caliban provides implicit "),s("code",[t._v("Schema")]),t._v(" types for the standard "),s("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 "),s("code",[t._v("ArgBuilder")]),t._v(" companion object. For instance, you can specify an "),s("code",[t._v("instantEpoch")]),t._v("\nto handle instants which are encoded using a "),s("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 "),s("code",[t._v("DateTimeFormatter")]),t._v(" to handle your particular date time needs.")]),t._v(" "),s("h2",{attrs:{id:"custom-types"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#custom-types"}},[t._v("#")]),t._v(" Custom types")]),t._v(" "),s("p",[t._v("Caliban provides auto-derivation for common types such as "),s("code",[t._v("Int")]),t._v(", "),s("code",[t._v("String")]),t._v(", "),s("code",[t._v("List")]),t._v(", "),s("code",[t._v("Option")]),t._v(", etc. but you can also support your own types by providing an implicit instance of "),s("code",[t._v("caliban.schema.Schema")]),t._v(".")]),t._v(" "),s("p",[t._v("An easy way to do this is to reuse existing instances and use "),s("code",[t._v("contramap")]),t._v(" to map from your type to the original type. Here's an example of creating an instance for "),s("a",{attrs:{href:"https://github.com/fthomas/refined",target:"_blank",rel:"noopener noreferrer"}},[t._v("refined"),s("OutboundLink")],1),t._v("'s "),s("code",[t._v("NonEmptyString")]),t._v(" reusing existing instance for "),s("code",[t._v("String")]),t._v(" (if you use "),s("code",[t._v("refined")]),t._v(", you might want to look at "),s("a",{attrs:{href:"https://github.com/niqdev/caliban-extras#caliban-refined",target:"_blank",rel:"noopener noreferrer"}},[t._v("caliban-refined"),s("OutboundLink")],1),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("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("implicit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" nonEmptyStringSchema"),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(" NonEmptyString"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("stringSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("contramap"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("You can also use the "),s("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 "),s("code",[t._v("ResponseValue")]),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("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("implicit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" unitSchema"),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(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" scalarSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Unit"')]),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(" _ "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ObjectValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Nil"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("If you are using a custom type as part of the input you also have to provide an implicit instance of "),s("code",[t._v("caliban.schema.ArgBuilder")]),t._v(". For example here's how to do that for "),s("code",[t._v("java.time.LocalDate")]),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(" localDateArgBuilder"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ArgBuilder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("LocalDate"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[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(" StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),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 Try"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("LocalDate"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parse"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),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 punctuation"}},[t._v(".")]),t._v("fold"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ex "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" Left"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Can\'t parse $value into a LocalDate"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" innerThrowable "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ex"),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(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Right"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),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 keyword"}},[t._v("case")]),t._v(" other "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" Left"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Can\'t build a LocalDate from input $other"')]),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 punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("Value classes ("),s("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(" "),s("h2",{attrs:{id:"code-generation"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#code-generation"}},[t._v("#")]),t._v(" Code generation")]),t._v(" "),s("p",[t._v("Caliban can automatically generate Scala code from a GraphQL schema.")]),t._v(" "),s("p",[t._v("In order to use this feature, add the "),s("code",[t._v("caliban-codegen-sbt")]),t._v(" sbt plugin to your "),s("code",[t._v("project/plugins.sbt")]),t._v(" file:")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[t._v("addSbtPlugin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),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("%")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-codegen-sbt"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1.2.1"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("And enable it in your "),s("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[t._v("enablePlugins"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CalibanPlugin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("Then call the "),s("code",[t._v("calibanGenSchema")]),t._v(" sbt command.")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[t._v("calibanGenSchema schemaPath outputPath "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("scalafmtPath path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("headers name"),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("name2"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("value2"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("packageName name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("effect fqdn"),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(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("scalarMappings gqlType"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("f"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("q"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("d"),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("Type"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("gqlType2"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("f"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("q"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("d"),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("Type2"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("imports a"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("b"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("c"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("c"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("d"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("E"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("abstractEffectType "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\ncalibanGenSchema project"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("graphql src"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("main"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("MyAPI"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("scala\n")])])]),s("p",[t._v("This command will create a Scala file in "),s("code",[t._v("outputPath")]),t._v(" containing all the types defined in the provided GraphQL schema defined at "),s("code",[t._v("schemaPath")]),t._v(". Instead of a file, you can provide a URL and the schema will be obtained using introspection.")]),t._v(" "),s("p",[t._v("The generated code will be formatted with Scalafmt using the configuration defined by "),s("code",[t._v("--scalafmtPath")]),t._v(" option (default: "),s("code",[t._v(".scalafmt.conf")]),t._v("). If you provide a URL for "),s("code",[t._v("schemaPath")]),t._v(", you can provide request headers with "),s("code",[t._v("--headers")]),t._v(" option.")]),t._v(" "),s("p",[t._v("The package of the generated code is derived from the folder of "),s("code",[t._v("outputPath")]),t._v(". This can be overridden by providing an alternative package with the "),s("code",[t._v("--packageName")]),t._v(" option.")]),t._v(" "),s("p",[t._v("By default, each Query and Mutation will be wrapped into a "),s("code",[t._v("zio.UIO")]),t._v(" effect. This can be overridden by providing an alternative effect with the "),s("code",[t._v("--effect")]),t._v(" option.")]),t._v(" "),s("p",[t._v("You can also indicate that the effect type is abstract via "),s("code",[t._v("--abstractEffectType true")]),t._v(", in which case "),s("code",[t._v("Query")]),t._v(" will be replaced by "),s("code",[t._v("Query[F[_]]")]),t._v(" and so on (note "),s("code",[t._v("F")]),t._v(" will be used unless "),s("code",[t._v("--effect ")]),t._v(" is explicitly given in which case "),s("code",[t._v("")]),t._v(" would be used in place of "),s("code",[t._v("F")]),t._v(").")]),t._v(" "),s("p",[t._v("If you want to force a mapping between a GraphQL type and a Scala class (such as scalars), you can use the\n"),s("code",[t._v("--scalarMappings")]),t._v(" option. Also you can add additional imports by providing "),s("code",[t._v("--imports")]),t._v(" option.")]),t._v(" "),s("h2",{attrs:{id:"building-schemas-by-hand"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#building-schemas-by-hand"}},[t._v("#")]),t._v(" Building Schemas by hand")]),t._v(" "),s("p",[t._v("Sometimes for whatever reason schema generation fails. This can happen if your schema has co-recursive types and Magnolia 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(" "),s("p",[t._v("Consider the case where you have three types which create cyclical dependencies on one another")]),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(" Group"),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(" users"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("User"),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(" parent"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Option"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Group"),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(" organization"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Organization"),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 keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Organization"),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(" groups"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Group"),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("\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(" User"),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(" group"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Group"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("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 "),s("code",[t._v("NullPointerException")]),t._v(". To help the compiler out we can hand generate the types for these case classes instead.")]),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("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(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("obj"),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("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" groupSchema"),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(" Group"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" obj"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Group"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"A group of users"')]),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("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" ft "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),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 punctuation"}},[t._v(".")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"users"')]),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 punctuation"}},[t._v(".")]),t._v("users"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"parent"')]),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 punctuation"}},[t._v(".")]),t._v("parent"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"organization"')]),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 punctuation"}},[t._v(".")]),t._v("organization"),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 keyword"}},[t._v("implicit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" orgSchema"),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(" Organization"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" obj"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Organization"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"An organization of groups"')]),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("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" ft "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),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 punctuation"}},[t._v(".")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"groups"')]),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 punctuation"}},[t._v(".")]),t._v("groups"),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\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" userSchema"),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(" User"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" obj"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"User"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"A user of the service"')]),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("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" ft "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),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 punctuation"}},[t._v(".")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"group"')]),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 punctuation"}},[t._v(".")]),t._v("group"),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")])])])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/17.eff2b8a2.js b/docs/assets/js/17.eff2b8a2.js new file mode 100644 index 0000000000..52a8fcffa3 --- /dev/null +++ b/docs/assets/js/17.eff2b8a2.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[17],{402:function(t,a,s){"use strict";s.r(a);var e=s(54),n=Object(e.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"schemas"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#schemas"}},[t._v("#")]),t._v(" Schemas")]),t._v(" "),s("p",[t._v("A GraphQL schema will be derived automatically at compile-time (no reflection) from the types present in your resolver.\nThe table below shows how common Scala types are converted to GraphQL types.")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Scala Type")]),t._v(" "),s("th",[t._v("GraphQL Type")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[t._v("Boolean")]),t._v(" "),s("td",[t._v("Boolean")])]),t._v(" "),s("tr",[s("td",[t._v("Int")]),t._v(" "),s("td",[t._v("Int")])]),t._v(" "),s("tr",[s("td",[t._v("Float")]),t._v(" "),s("td",[t._v("Float")])]),t._v(" "),s("tr",[s("td",[t._v("Double")]),t._v(" "),s("td",[t._v("Float")])]),t._v(" "),s("tr",[s("td",[t._v("String")]),t._v(" "),s("td",[t._v("String")])]),t._v(" "),s("tr",[s("td",[t._v("java.util.UUID")]),t._v(" "),s("td",[t._v("ID")])]),t._v(" "),s("tr",[s("td",[t._v("Unit")]),t._v(" "),s("td",[t._v("Unit (custom scalar)")])]),t._v(" "),s("tr",[s("td",[t._v("Long")]),t._v(" "),s("td",[t._v("Long (custom scalar)")])]),t._v(" "),s("tr",[s("td",[t._v("BigInt")]),t._v(" "),s("td",[t._v("BigInt (custom scalar)")])]),t._v(" "),s("tr",[s("td",[t._v("BigDecimal")]),t._v(" "),s("td",[t._v("BigDecimal (custom scalar)")])]),t._v(" "),s("tr",[s("td",[t._v("java.time.Instant")]),t._v(" "),s("td",[t._v("Instant (custom scalar)")])]),t._v(" "),s("tr",[s("td",[t._v("java.time.LocalDate")]),t._v(" "),s("td",[t._v("LocalDate (custom scalar)")])]),t._v(" "),s("tr",[s("td",[t._v("java.time.LocalTime")]),t._v(" "),s("td",[t._v("LocalTime (custom scalar)")])]),t._v(" "),s("tr",[s("td",[t._v("java.time.LocalDateTime")]),t._v(" "),s("td",[t._v("LocalDateTime (custom scalar)")])]),t._v(" "),s("tr",[s("td",[t._v("java.time.OffsetDateTime")]),t._v(" "),s("td",[t._v("OffsetDateTime (custom scalar)")])]),t._v(" "),s("tr",[s("td",[t._v("java.time.ZonedDateTime")]),t._v(" "),s("td",[t._v("ZonedDateTime (custom scalar)")])]),t._v(" "),s("tr",[s("td",[t._v("Case Class")]),t._v(" "),s("td",[t._v("Object")])]),t._v(" "),s("tr",[s("td",[t._v("Sealed Trait")]),t._v(" "),s("td",[t._v("Enum or Union")])]),t._v(" "),s("tr",[s("td",[t._v("Option[A]")]),t._v(" "),s("td",[t._v("Nullable A")])]),t._v(" "),s("tr",[s("td",[t._v("List[A]")]),t._v(" "),s("td",[t._v("List of A")])]),t._v(" "),s("tr",[s("td",[t._v("Set[A]")]),t._v(" "),s("td",[t._v("List of A")])]),t._v(" "),s("tr",[s("td",[t._v("Seq[A]")]),t._v(" "),s("td",[t._v("List of A")])]),t._v(" "),s("tr",[s("td",[t._v("Vector[A]")]),t._v(" "),s("td",[t._v("List of A")])]),t._v(" "),s("tr",[s("td",[t._v("A => B")]),t._v(" "),s("td",[t._v("A and B")])]),t._v(" "),s("tr",[s("td",[t._v("(A, B)")]),t._v(" "),s("td",[t._v("Object with 2 fields "),s("code",[t._v("_1")]),t._v(" and "),s("code",[t._v("_2")])])]),t._v(" "),s("tr",[s("td",[t._v("Either[A, B]")]),t._v(" "),s("td",[t._v("Object with 2 nullable fields "),s("code",[t._v("left")]),t._v(" and "),s("code",[t._v("right")])])]),t._v(" "),s("tr",[s("td",[t._v("Map[A, B]")]),t._v(" "),s("td",[t._v("List of Object with 2 fields "),s("code",[t._v("key")]),t._v(" and "),s("code",[t._v("value")])])]),t._v(" "),s("tr",[s("td",[t._v("ZIO[R, Nothing, A]")]),t._v(" "),s("td",[t._v("A")])]),t._v(" "),s("tr",[s("td",[t._v("ZIO[R, Throwable, A]")]),t._v(" "),s("td",[t._v("Nullable A")])]),t._v(" "),s("tr",[s("td",[t._v("Future[A]")]),t._v(" "),s("td",[t._v("Nullable A")])]),t._v(" "),s("tr",[s("td",[t._v("ZStream[R, Throwable, A]")]),t._v(" "),s("td",[t._v("A (subscription) or List of A (query, mutation)")])]),t._v(" "),s("tr",[s("td",[t._v("Json (from "),s("a",{attrs:{href:"https://github.com/circe/circe",target:"_blank",rel:"noopener noreferrer"}},[t._v("Circe"),s("OutboundLink")],1),t._v(")")]),t._v(" "),s("td",[t._v("Json (custom scalar, need "),s("code",[t._v("import caliban.interop.circe.json._")]),t._v(")")])]),t._v(" "),s("tr",[s("td",[t._v("Json (from "),s("a",{attrs:{href:"https://github.com/playframework/play-json",target:"_blank",rel:"noopener noreferrer"}},[t._v("play-json"),s("OutboundLink")],1),t._v(")")]),t._v(" "),s("td",[t._v("Json (custom scalar, need "),s("code",[t._v("import caliban.interop.play.json._")]),t._v(")")])])])]),t._v(" "),s("p",[t._v("See the "),s("a",{attrs:{href:"#custom-types"}},[t._v("Custom Types")]),t._v(" section to find out how to support your own types.")]),t._v(" "),s("p",[t._v("If you want Caliban to support other standard types, feel free to "),s("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/issues",target:"_blank",rel:"noopener noreferrer"}},[t._v("file an issue"),s("OutboundLink")],1),t._v(" or even a PR.")]),t._v(" "),s("div",{staticClass:"custom-block warning"},[s("p",{staticClass:"custom-block-title"},[t._v("Schema derivation issues")]),t._v(" "),s("p",[t._v("The schema derivation sometimes has some trouble generating schemas with a lot of nested types, or types reused in multiple places.\nTo deal with this, you can declare schemas for your case classes and sealed traits explicitly:")]),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(" roleSchema "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Role"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),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(" characterSchema "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n")])])]),s("p",[t._v("Make sure those implicits are in scope when you call "),s("code",[t._v("graphQL(...)")]),t._v(". This will make derivation's job easier by pre-generating schemas for those classes and re-using them when needed.\nThis will also improve compilation times and generate less bytecode.")]),t._v(" "),s("p",[t._v("In Scala 2, if the derivation fails and you're not sure why, you can also call Magnolia's macro directly by using "),s("code",[t._v("genMacro")]),t._v(".\nThe compilation will return better error messages in case something is missing:")]),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(" characterSchema "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("genMacro"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema\n")])])]),s("p",[t._v("In Scala 3, derivation doesn't support value classes, opaque types and nested sealed traits.")])]),t._v(" "),s("h2",{attrs:{id:"enums-unions-interfaces"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#enums-unions-interfaces"}},[t._v("#")]),t._v(" Enums, unions, interfaces")]),t._v(" "),s("p",[t._v("A sealed trait will be converted to a different GraphQL type depending on its content:")]),t._v(" "),s("ul",[s("li",[t._v("a sealed trait with only case objects will be converted to an "),s("code",[t._v("ENUM")])]),t._v(" "),s("li",[t._v("a sealed trait with only case classes will be converted to a "),s("code",[t._v("UNION")])])]),t._v(" "),s("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 '),s("code",[t._v("_")]),t._v(" which is not queryable.")]),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("sealed")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" ORIGIN\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" ORIGIN "),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("object")]),t._v(" EARTH "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" ORIGIN\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" MARS "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" ORIGIN\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" BELT "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" ORIGIN\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("The snippet above will produce the following GraphQL type:")]),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("enum")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("BELT")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("EARTH")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("MARS")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("Here's an example of union:")]),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("sealed")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Role\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Role "),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(" Captain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("shipName"),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(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\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(" Engineer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("specialty"),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(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Mechanic "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("The snippet above will produce the following GraphQL type:")]),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("union")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Role")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("Captain")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("Engineer")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("Mechanic")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Captain")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("shipName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token operator"}},[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("type")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Engineer")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("specialty")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token operator"}},[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("type")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mechanic")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("_")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("Boolean")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("If your type needs to be shared between multiple unions you can use the "),s("code",[t._v("@GQLValueType")]),t._v(" annotation to have caliban\nproxy to another type beyond the sealed trait.")]),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(" Pilot"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("callSign"),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("sealed")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Role\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Role "),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(" Captain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("shipName"),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(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\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(" Engineer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("specialty"),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(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n \n "),s("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLValueType")]),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(" Proxy"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("pilot"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Pilot"),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("This will produce the following GraphQL Types:")]),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("union")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Role")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("Captain")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("Engineer")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("Pilot")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Captain")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("shipName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token operator"}},[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("type")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Engineer")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("specialty")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token operator"}},[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("type")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Pilot")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("callSign")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("If you prefer an "),s("code",[t._v("Interface")]),t._v(" instead of a "),s("code",[t._v("Union")]),t._v(" type, add the "),s("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(" "),s("p",[t._v("If you prefer to have a "),s("code",[t._v("Union")]),t._v(" type instead of an "),s("code",[t._v("Enum")]),t._v(", even when the sealed trait contains only objects, add the "),s("code",[t._v("@GQLUnion")]),t._v(" annotation.")]),t._v(" "),s("h2",{attrs:{id:"arguments"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#arguments"}},[t._v("#")]),t._v(" Arguments")]),t._v(" "),s("p",[t._v("To declare a field that take arguments, create a dedicated case class representing the arguments and make the field a "),s("em",[t._v("function")]),t._v(" from this class to the result type.")]),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(" FilterArgs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("origin"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Origin"),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 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("characters"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FilterArgs "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("The snippet above will produce the following GraphQL type:")]),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("type")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Queries")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("characters")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("origin")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),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 punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("Caliban provides auto-derivation for common types such as "),s("code",[t._v("Int")]),t._v(", "),s("code",[t._v("String")]),t._v(", "),s("code",[t._v("List")]),t._v(", "),s("code",[t._v("Option")]),t._v(", etc. but you can also support your own types by providing an implicit instance of "),s("code",[t._v("caliban.schema.ArgBuilder")]),t._v(".")]),t._v(" "),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),s("p",[t._v("There is no "),s("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(" "),s("h2",{attrs:{id:"effects"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#effects"}},[t._v("#")]),t._v(" Effects")]),t._v(" "),s("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(" "),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(" Queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),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("List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),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("\n character"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CharacterName "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" RIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Console"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Character"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("If you don't use ZIO environment ("),s("code",[t._v("R")]),t._v(" = "),s("code",[t._v("Any")]),t._v("), there is nothing special to do to get it working.")]),t._v(" "),s("p",[t._v("If you require a ZIO environment, you will need to have the content of "),s("code",[t._v("caliban.schema.GenericSchema[R]")]),t._v(" for your custom "),s("code",[t._v("R")]),t._v(" in scope when you call "),s("code",[t._v("graphQL(...)")]),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("object")]),t._v(" schema "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" GenericSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),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("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("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Necessary for scala 3 due to https://docs.scala-lang.org/scala3/book/ca-given-imports.html")]),t._v("\n")])])]),s("p",[t._v("Note: If you ever need to declare schemas explicitly (by calling "),s("code",[t._v("gen")]),t._v(" directly, as explained above), and you require a ZIO environment (explained in this section),\nthen you must use the "),s("code",[t._v("gen")]),t._v(" from this "),s("code",[t._v("object schema")]),t._v(". If you call "),s("code",[t._v("gen")]),t._v(" to derive schemas in the same module and you "),s("code",[t._v("import schema._")]),t._v(" at the top of this module,\nyou'd be fine. However, if you derive schemas in a separate module, then make sure you import this schema object in that module so that you'll be using the "),s("code",[t._v("gen")]),t._v(" from the "),s("code",[t._v("schema")]),t._v(" object.")]),t._v(" "),s("h2",{attrs:{id:"annotations"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#annotations"}},[t._v("#")]),t._v(" Annotations")]),t._v(" "),s("p",[t._v("Caliban supports a few annotations to enrich data types:")]),t._v(" "),s("ul",[s("li",[s("code",[t._v('@GQLName("name")')]),t._v(" allows you to specify a different name for a data type or a field.")]),t._v(" "),s("li",[s("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 "),s("code",[t._v("Input")]),t._v(" is appended to the type name).")]),t._v(" "),s("li",[s("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(" "),s("li",[s("code",[t._v('@GQLDeprecated("reason")')]),t._v(" allows deprecating a field or an enum value.")]),t._v(" "),s("li",[s("code",[t._v("@GQLInterface")]),t._v(" to force a sealed trait generating an interface instead of a union.")]),t._v(" "),s("li",[s("code",[t._v("@GQLDirective(directive: Directive)")]),t._v(" to add a directive to a field or type.")]),t._v(" "),s("li",[s("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 "),s("code",[t._v("isScalar")]),t._v(" is true, it will generate a scalar named after the case class (default: false).")]),t._v(" "),s("li",[s("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(" "),s("h2",{attrs:{id:"java-8-time-types"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#java-8-time-types"}},[t._v("#")]),t._v(" Java 8 Time types")]),t._v(" "),s("p",[t._v("Caliban provides implicit "),s("code",[t._v("Schema")]),t._v(" types for the standard "),s("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 "),s("code",[t._v("ArgBuilder")]),t._v(" companion object. For instance, you can specify an "),s("code",[t._v("instantEpoch")]),t._v("\nto handle instants which are encoded using a "),s("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 "),s("code",[t._v("DateTimeFormatter")]),t._v(" to handle your particular date time needs.")]),t._v(" "),s("h2",{attrs:{id:"custom-types"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#custom-types"}},[t._v("#")]),t._v(" Custom types")]),t._v(" "),s("p",[t._v("Caliban provides auto-derivation for common types such as "),s("code",[t._v("Int")]),t._v(", "),s("code",[t._v("String")]),t._v(", "),s("code",[t._v("List")]),t._v(", "),s("code",[t._v("Option")]),t._v(", etc. but you can also support your own types by providing an implicit instance of "),s("code",[t._v("caliban.schema.Schema")]),t._v(".")]),t._v(" "),s("p",[t._v("An easy way to do this is to reuse existing instances and use "),s("code",[t._v("contramap")]),t._v(" to map from your type to the original type. Here's an example of creating an instance for "),s("a",{attrs:{href:"https://github.com/fthomas/refined",target:"_blank",rel:"noopener noreferrer"}},[t._v("refined"),s("OutboundLink")],1),t._v("'s "),s("code",[t._v("NonEmptyString")]),t._v(" reusing existing instance for "),s("code",[t._v("String")]),t._v(" (if you use "),s("code",[t._v("refined")]),t._v(", you might want to look at "),s("a",{attrs:{href:"https://github.com/niqdev/caliban-extras#caliban-refined",target:"_blank",rel:"noopener noreferrer"}},[t._v("caliban-refined"),s("OutboundLink")],1),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("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("implicit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" nonEmptyStringSchema"),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(" NonEmptyString"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("stringSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("contramap"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("You can also use the "),s("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 "),s("code",[t._v("ResponseValue")]),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("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("implicit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" unitSchema"),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(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" scalarSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Unit"')]),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(" _ "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ObjectValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Nil"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("If you are using a custom type as part of the input you also have to provide an implicit instance of "),s("code",[t._v("caliban.schema.ArgBuilder")]),t._v(". For example here's how to do that for "),s("code",[t._v("java.time.LocalDate")]),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(" localDateArgBuilder"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ArgBuilder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("LocalDate"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[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(" StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),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 Try"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("LocalDate"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parse"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),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 punctuation"}},[t._v(".")]),t._v("fold"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ex "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" Left"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Can\'t parse $value into a LocalDate"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" innerThrowable "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ex"),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(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Right"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),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 keyword"}},[t._v("case")]),t._v(" other "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" Left"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Can\'t build a LocalDate from input $other"')]),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 punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("Value classes ("),s("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(" "),s("h2",{attrs:{id:"code-generation"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#code-generation"}},[t._v("#")]),t._v(" Code generation")]),t._v(" "),s("p",[t._v("Caliban can automatically generate Scala code from a GraphQL schema.")]),t._v(" "),s("p",[t._v("In order to use this feature, add the "),s("code",[t._v("caliban-codegen-sbt")]),t._v(" sbt plugin to your "),s("code",[t._v("project/plugins.sbt")]),t._v(" file:")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[t._v("addSbtPlugin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),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("%")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-codegen-sbt"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1.2.1"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("And enable it in your "),s("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[t._v("enablePlugins"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CalibanPlugin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("Then call the "),s("code",[t._v("calibanGenSchema")]),t._v(" sbt command.")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[t._v("calibanGenSchema schemaPath outputPath "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("scalafmtPath path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("headers name"),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("name2"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("value2"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("packageName name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("effect fqdn"),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(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("scalarMappings gqlType"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("f"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("q"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("d"),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("Type"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("gqlType2"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("f"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("q"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("d"),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("Type2"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("imports a"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("b"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("c"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("c"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("d"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("E"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("abstractEffectType "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\ncalibanGenSchema project"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("graphql src"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("main"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("MyAPI"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("scala\n")])])]),s("p",[t._v("This command will create a Scala file in "),s("code",[t._v("outputPath")]),t._v(" containing all the types defined in the provided GraphQL schema defined at "),s("code",[t._v("schemaPath")]),t._v(". Instead of a file, you can provide a URL and the schema will be obtained using introspection.")]),t._v(" "),s("p",[t._v("The generated code will be formatted with Scalafmt using the configuration defined by "),s("code",[t._v("--scalafmtPath")]),t._v(" option (default: "),s("code",[t._v(".scalafmt.conf")]),t._v("). If you provide a URL for "),s("code",[t._v("schemaPath")]),t._v(", you can provide request headers with "),s("code",[t._v("--headers")]),t._v(" option.")]),t._v(" "),s("p",[t._v("The package of the generated code is derived from the folder of "),s("code",[t._v("outputPath")]),t._v(". This can be overridden by providing an alternative package with the "),s("code",[t._v("--packageName")]),t._v(" option.")]),t._v(" "),s("p",[t._v("By default, each Query and Mutation will be wrapped into a "),s("code",[t._v("zio.UIO")]),t._v(" effect. This can be overridden by providing an alternative effect with the "),s("code",[t._v("--effect")]),t._v(" option.")]),t._v(" "),s("p",[t._v("You can also indicate that the effect type is abstract via "),s("code",[t._v("--abstractEffectType true")]),t._v(", in which case "),s("code",[t._v("Query")]),t._v(" will be replaced by "),s("code",[t._v("Query[F[_]]")]),t._v(" and so on (note "),s("code",[t._v("F")]),t._v(" will be used unless "),s("code",[t._v("--effect ")]),t._v(" is explicitly given in which case "),s("code",[t._v("")]),t._v(" would be used in place of "),s("code",[t._v("F")]),t._v(").")]),t._v(" "),s("p",[t._v("If you want to force a mapping between a GraphQL type and a Scala class (such as scalars), you can use the\n"),s("code",[t._v("--scalarMappings")]),t._v(" option. Also you can add additional imports by providing "),s("code",[t._v("--imports")]),t._v(" option.")]),t._v(" "),s("h2",{attrs:{id:"building-schemas-by-hand"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#building-schemas-by-hand"}},[t._v("#")]),t._v(" Building Schemas by hand")]),t._v(" "),s("p",[t._v("Sometimes for whatever reason schema generation fails. This can happen if your schema has co-recursive types and Magnolia 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(" "),s("p",[t._v("Consider the case where you have three types which create cyclical dependencies on one another")]),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(" Group"),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(" users"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("User"),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(" parent"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Option"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Group"),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(" organization"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Organization"),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 keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Organization"),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(" groups"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Group"),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("\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(" User"),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(" group"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Group"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("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 "),s("code",[t._v("NullPointerException")]),t._v(". To help the compiler out we can hand generate the types for these case classes instead.")]),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("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(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("obj"),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("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" groupSchema"),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(" Group"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" obj"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Group"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"A group of users"')]),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("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" ft "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),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 punctuation"}},[t._v(".")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"users"')]),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 punctuation"}},[t._v(".")]),t._v("users"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"parent"')]),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 punctuation"}},[t._v(".")]),t._v("parent"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"organization"')]),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 punctuation"}},[t._v(".")]),t._v("organization"),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 keyword"}},[t._v("implicit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" orgSchema"),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(" Organization"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" obj"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Organization"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"An organization of groups"')]),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("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" ft "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),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 punctuation"}},[t._v(".")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"groups"')]),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 punctuation"}},[t._v(".")]),t._v("groups"),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\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" userSchema"),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(" User"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" obj"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"User"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"A user of the service"')]),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("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" ft "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),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 punctuation"}},[t._v(".")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"group"')]),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 punctuation"}},[t._v(".")]),t._v("group"),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")])])])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/18.c4fbc130.js b/docs/assets/js/18.77b2e100.js similarity index 99% rename from docs/assets/js/18.c4fbc130.js rename to docs/assets/js/18.77b2e100.js index b520a82af9..1f12550b2b 100644 --- a/docs/assets/js/18.c4fbc130.js +++ b/docs/assets/js/18.77b2e100.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[18],{391:function(t,s,a){"use strict";a.r(s);var n=a(46),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"stitching"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#stitching"}},[t._v("#")]),t._v(" Stitching")]),t._v(" "),a("p",[a("strong",[t._v("Stitching")]),t._v(" is a part of "),a("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(" "),a("p",[t._v("In general, Federation should be your preferred choice.")]),t._v(" "),a("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(" "),a("h2",{attrs:{id:"dependencies"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#dependencies"}},[t._v("#")]),t._v(" Dependencies")]),t._v(" "),a("p",[t._v("In order to use stitching, add "),a("code",[t._v("caliban-tools")]),t._v(" to your dependencies:")]),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-tools"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1.2.1"')]),t._v("\n")])])]),a("h2",{attrs:{id:"stitching-in-action"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#stitching-in-action"}},[t._v("#")]),t._v(" Stitching in Action")]),t._v(" "),a("p",[t._v("Let's start out by defining our API. We'll have "),a("code",[t._v("AppUser")]),t._v(" profiles, that has a linked "),a("code",[t._v("featuredRepository")]),t._v(". For the "),a("code",[t._v("featuredRepository")]),t._v(", we want to leverage "),a("a",{attrs:{href:"https://docs.github.com/en/graphql",target:"_blank",rel:"noopener noreferrer"}},[t._v("Github's GraphQL API"),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("object")]),t._v(" StitchingExample "),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("ZEnv"),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("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" AppUser"),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(" 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(" featuredRepository"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Repository"),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(" Repository"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("owner"),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(" 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\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(" GetUserQuery"),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(" repository"),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("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("\n GetUser"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GetUserQuery "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" URIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ZEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" AppUser"),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("\n RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GetUser "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" query "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n random"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nextUUID"),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("uuid "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n AppUser"),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(" uuid"),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 name "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" query"),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("\n featuredRepository "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Repository"),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("name"),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("repository"),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("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("Now let's integrate with the Github API!")]),t._v(" "),a("p",[t._v("In order to do this we're going to do a couple of things:")]),t._v(" "),a("ol",[a("li",[t._v("Load the introspection schema from Github's API")]),t._v(" "),a("li",[t._v("Parse the introspected schema into a "),a("code",[t._v("caliban.introspection.adt.__Schema")])]),t._v(" "),a("li",[t._v("Use the parsed schema to generate an "),a("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(" "),a("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(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" GITHUB_API "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https://api.github.com/graphql"')]),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(" "),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 sttpClient "),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("environment"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("SttpClient"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 1")]),t._v("\n schemaLoader "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" SchemaLoader"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromIntrospection"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GITHUB_API"),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("\n schema "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" schemaLoader"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("load\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 2")]),t._v("\n remoteSchema "),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("fromOption"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RemoteSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parseRemoteSchema"),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("\n remoteSchemaResolvers "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" RemoteSchemaResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("remoteSchema"),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("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 3")]),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(" githubProfileSchema"),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("ZEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Repository"),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 remoteSchemaResolvers\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("remoteResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Repository"')]),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("// 4")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Here we need to translate our local `Repository` case class into")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// a top-level query which can be issued towards Github's API.")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We do this by accepting a `caliban.execution.Field`, representing")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// all the selected fields for a repository and map that to the")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// top-level `repository` query in the Github API.")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This means the final query will end up looking something like this:")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// query {")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// repository(owner: r.args.owner, name: r.args.name) {")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// . ")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// }")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// }")]),t._v("\n RemoteResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromFunction"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ResolveRequest"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Repository"),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("\n r"),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("copy"),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 string"}},[t._v('"repository"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n arguments "),a("span",{pre:!0,attrs:{class:"token operator"}},[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 string"}},[t._v('"owner"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),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("r"),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("owner"),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 string"}},[t._v('"name"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),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("r"),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("\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(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromUrl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GITHUB_API"),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("provide"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sttpClient"),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("However, when running this we will experience failing requests due to "),a("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 "),a("code",[t._v("GITHUB_TOKEN")]),t._v(" in our environment.")]),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(" Configuration"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("githubToken"),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("object")]),t._v(" Configuration "),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(" fromEnvironment "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),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 githubToken "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" read"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GITHUB_TOKEN"')]),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(" Configuration"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("githubToken"),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("toLayer\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" read"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),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(" Task"),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(" "),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("effect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n sys"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("env"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),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("We can now update the introspection query to use our token:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v(" "),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(" "),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 config "),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("environment"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Has"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Configuration"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n schemaLoader "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" SchemaLoader"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromIntrospection"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GITHUB_API"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Some"),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("\n Options"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Header"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Authorization"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n s"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bearer ${config.get.githubToken}"')]),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("span",{pre:!0,attrs:{class:"token comment"}},[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 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("as well as update our resolver to authorize our request.")]),t._v(" "),a("p",[t._v("In order to do this, we can use "),a("code",[t._v("RemoteResolver[R, E, A, B]")]),t._v(" which lets us compose resolution steps via "),a("code",[t._v(">>>")]),t._v(".")]),t._v(" "),a("p",[t._v("In order to make this code easier, we can extract the mechanics around sending the actual request:")]),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(" apiRequest "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n RemoteResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toQuery "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),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("GITHUB_API"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromFunctionM"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" HttpRequest"),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 "),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 config "),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("service"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Configuration"),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(" r"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("header"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Authorization"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" s"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bearer ${config.githubToken}"')]),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 operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("execute "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("unwrap\n")])])]),a("p",[t._v("And now we can use our new "),a("code",[t._v("apiRequest")]),t._v(" when resolving our "),a("code",[t._v("Schema[ZEnv, Repository]")]),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("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" githubProfileSchema"),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("ZEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Repository"),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 remoteSchemaResolvers\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("remoteResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Repository"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n RemoteResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromFunction"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ResolveRequest"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Repository"),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("\n r"),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("copy"),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 string"}},[t._v('"repository"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n arguments "),a("span",{pre:!0,attrs:{class:"token operator"}},[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 string"}},[t._v('"owner"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),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("r"),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("owner"),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 string"}},[t._v('"name"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),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("r"),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("\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(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" apiRequest\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("provide"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sttpClient "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("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(" "),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("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("GetUser")]),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(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ghostdogpr"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("repository")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban"')]),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 property"}},[t._v("id")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("name")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token object"}},[t._v("featuredRepository")]),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("pullRequests")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("states")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("OPEN")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("first")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),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 object"}},[t._v("edges")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token object"}},[t._v("node")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("title")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token object"}},[t._v("author")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("login")]),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("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("See the "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/stitching",target:"_blank",rel:"noopener noreferrer"}},[t._v("examples directory"),a("OutboundLink")],1),t._v(" for a full example.")]),t._v(" "),a("h2",{attrs:{id:"things-not-yet-supported"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#things-not-yet-supported"}},[t._v("#")]),t._v(" Things not yet supported")]),t._v(" "),a("ul",[a("li",[t._v("Type renaming.")]),t._v(" "),a("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([[18],{403:function(t,s,a){"use strict";a.r(s);var n=a(54),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"stitching"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#stitching"}},[t._v("#")]),t._v(" Stitching")]),t._v(" "),a("p",[a("strong",[t._v("Stitching")]),t._v(" is a part of "),a("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(" "),a("p",[t._v("In general, Federation should be your preferred choice.")]),t._v(" "),a("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(" "),a("h2",{attrs:{id:"dependencies"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#dependencies"}},[t._v("#")]),t._v(" Dependencies")]),t._v(" "),a("p",[t._v("In order to use stitching, add "),a("code",[t._v("caliban-tools")]),t._v(" to your dependencies:")]),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-tools"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1.2.1"')]),t._v("\n")])])]),a("h2",{attrs:{id:"stitching-in-action"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#stitching-in-action"}},[t._v("#")]),t._v(" Stitching in Action")]),t._v(" "),a("p",[t._v("Let's start out by defining our API. We'll have "),a("code",[t._v("AppUser")]),t._v(" profiles, that has a linked "),a("code",[t._v("featuredRepository")]),t._v(". For the "),a("code",[t._v("featuredRepository")]),t._v(", we want to leverage "),a("a",{attrs:{href:"https://docs.github.com/en/graphql",target:"_blank",rel:"noopener noreferrer"}},[t._v("Github's GraphQL API"),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("object")]),t._v(" StitchingExample "),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("ZEnv"),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("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" AppUser"),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(" 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(" featuredRepository"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Repository"),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(" Repository"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("owner"),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(" 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\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(" GetUserQuery"),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(" repository"),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("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("\n GetUser"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GetUserQuery "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" URIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ZEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" AppUser"),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("\n RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GetUser "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" query "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n random"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nextUUID"),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("uuid "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n AppUser"),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(" uuid"),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 name "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" query"),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("\n featuredRepository "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Repository"),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("name"),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("repository"),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("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("Now let's integrate with the Github API!")]),t._v(" "),a("p",[t._v("In order to do this we're going to do a couple of things:")]),t._v(" "),a("ol",[a("li",[t._v("Load the introspection schema from Github's API")]),t._v(" "),a("li",[t._v("Parse the introspected schema into a "),a("code",[t._v("caliban.introspection.adt.__Schema")])]),t._v(" "),a("li",[t._v("Use the parsed schema to generate an "),a("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(" "),a("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(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" GITHUB_API "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https://api.github.com/graphql"')]),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(" "),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 sttpClient "),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("environment"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("SttpClient"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 1")]),t._v("\n schemaLoader "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" SchemaLoader"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromIntrospection"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GITHUB_API"),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("\n schema "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" schemaLoader"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("load\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 2")]),t._v("\n remoteSchema "),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("fromOption"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RemoteSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parseRemoteSchema"),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("\n remoteSchemaResolvers "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" RemoteSchemaResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("remoteSchema"),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("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 3")]),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(" githubProfileSchema"),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("ZEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Repository"),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 remoteSchemaResolvers\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("remoteResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Repository"')]),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("// 4")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Here we need to translate our local `Repository` case class into")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// a top-level query which can be issued towards Github's API.")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We do this by accepting a `caliban.execution.Field`, representing")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// all the selected fields for a repository and map that to the")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// top-level `repository` query in the Github API.")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This means the final query will end up looking something like this:")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// query {")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// repository(owner: r.args.owner, name: r.args.name) {")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// . ")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// }")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// }")]),t._v("\n RemoteResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromFunction"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ResolveRequest"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Repository"),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("\n r"),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("copy"),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 string"}},[t._v('"repository"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n arguments "),a("span",{pre:!0,attrs:{class:"token operator"}},[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 string"}},[t._v('"owner"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),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("r"),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("owner"),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 string"}},[t._v('"name"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),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("r"),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("\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(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromUrl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GITHUB_API"),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("provide"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sttpClient"),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("However, when running this we will experience failing requests due to "),a("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 "),a("code",[t._v("GITHUB_TOKEN")]),t._v(" in our environment.")]),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(" Configuration"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("githubToken"),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("object")]),t._v(" Configuration "),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(" fromEnvironment "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),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 githubToken "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" read"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GITHUB_TOKEN"')]),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(" Configuration"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("githubToken"),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("toLayer\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" read"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),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(" Task"),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(" "),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("effect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n sys"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("env"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),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("We can now update the introspection query to use our token:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v(" "),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(" "),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 config "),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("environment"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Has"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Configuration"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n schemaLoader "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" SchemaLoader"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromIntrospection"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GITHUB_API"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Some"),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("\n Options"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Header"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Authorization"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n s"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bearer ${config.get.githubToken}"')]),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("span",{pre:!0,attrs:{class:"token comment"}},[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 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("as well as update our resolver to authorize our request.")]),t._v(" "),a("p",[t._v("In order to do this, we can use "),a("code",[t._v("RemoteResolver[R, E, A, B]")]),t._v(" which lets us compose resolution steps via "),a("code",[t._v(">>>")]),t._v(".")]),t._v(" "),a("p",[t._v("In order to make this code easier, we can extract the mechanics around sending the actual request:")]),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(" apiRequest "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n RemoteResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toQuery "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),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("GITHUB_API"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromFunctionM"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" HttpRequest"),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 "),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 config "),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("service"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Configuration"),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(" r"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("header"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Authorization"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" s"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bearer ${config.githubToken}"')]),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 operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("execute "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("unwrap\n")])])]),a("p",[t._v("And now we can use our new "),a("code",[t._v("apiRequest")]),t._v(" when resolving our "),a("code",[t._v("Schema[ZEnv, Repository]")]),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("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" githubProfileSchema"),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("ZEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Repository"),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 remoteSchemaResolvers\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("remoteResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Repository"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n RemoteResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromFunction"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ResolveRequest"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Repository"),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("\n r"),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("copy"),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 string"}},[t._v('"repository"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n arguments "),a("span",{pre:!0,attrs:{class:"token operator"}},[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 string"}},[t._v('"owner"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),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("r"),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("owner"),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 string"}},[t._v('"name"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),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("r"),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("\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(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" apiRequest\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("provide"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sttpClient "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("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(" "),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("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("GetUser")]),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(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ghostdogpr"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("repository")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban"')]),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 property"}},[t._v("id")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("name")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token object"}},[t._v("featuredRepository")]),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("pullRequests")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("states")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("OPEN")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("first")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),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 object"}},[t._v("edges")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token object"}},[t._v("node")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("title")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token object"}},[t._v("author")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("login")]),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("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("See the "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/examples/src/main/scala/example/stitching",target:"_blank",rel:"noopener noreferrer"}},[t._v("examples directory"),a("OutboundLink")],1),t._v(" for a full example.")]),t._v(" "),a("h2",{attrs:{id:"things-not-yet-supported"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#things-not-yet-supported"}},[t._v("#")]),t._v(" Things not yet supported")]),t._v(" "),a("ul",[a("li",[t._v("Type renaming.")]),t._v(" "),a("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/19.589dd5a6.js b/docs/assets/js/19.3f45935a.js similarity index 98% rename from docs/assets/js/19.589dd5a6.js rename to docs/assets/js/19.3f45935a.js index 12be6309d3..e0e18335bd 100644 --- a/docs/assets/js/19.589dd5a6.js +++ b/docs/assets/js/19.3f45935a.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[19],{392:function(t,a,s){"use strict";s.r(a);var n=s(46),e=Object(n.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"tools"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#tools"}},[t._v("#")]),t._v(" Tools")]),t._v(" "),s("p",[t._v("Caliban comes with a module called "),s("code",[t._v("caliban-tools")]),t._v(" that exposes some useful features:")]),t._v(" "),s("ul",[s("li",[t._v("all the code generation features from "),s("code",[t._v("caliban-codegen-sbt")]),t._v(", so that you can use them without sbt: see "),s("code",[t._v("caliban.tools.Codegen")]),t._v(".")]),t._v(" "),s("li",[t._v("a client for GraphQL introspection: see "),s("code",[t._v("caliban.tools.IntrospectionClient")]),t._v(".")]),t._v(" "),s("li",[t._v("utilities for "),s("RouterLink",{attrs:{to:"/docs/stitching.html"}},[t._v("stitching GraphQL schemas")]),t._v(".")],1),t._v(" "),s("li",[t._v("a way to compare GraphQL schemas, whether they come from Caliban or a remote server, see below.")])]),t._v(" "),s("h2",{attrs:{id:"dependency"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#dependency"}},[t._v("#")]),t._v(" Dependency")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v('libraryDependencies += "com.github.ghostdogpr" %% "caliban-tools" % "1.2.1"\n')])])]),s("h2",{attrs:{id:"schema-comparison"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#schema-comparison"}},[t._v("#")]),t._v(" Schema comparison")]),t._v(" "),s("p",[t._v("The object "),s("code",[t._v("caliban.tools.SchemaComparison")]),t._v(" exposes a "),s("code",[t._v("compare")]),t._v(" function that compares 2 schemas from different origins. It takes 2 "),s("code",[t._v("SchemaLoader")]),t._v(" as arguments, which you can build with one of the following constructors:")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("fromCaliban")]),t._v(": pass your "),s("code",[t._v("GraphQL")]),t._v(" object from Caliban")]),t._v(" "),s("li",[s("code",[t._v("fromFile")]),t._v(": pass the path to a file containing your schema in the GraphQL IDL")]),t._v(" "),s("li",[s("code",[t._v("fromString")]),t._v(": pass a string containing your schema in the GraphQL IDL")]),t._v(" "),s("li",[s("code",[t._v("fromIntrospection")]),t._v(": pass the URL of a GraphQL server supporting introspection")])]),t._v(" "),s("p",[t._v("The output of "),s("code",[t._v("compare")]),t._v(" is a "),s("code",[t._v("Task[List[SchemaComparisonChange]]")]),t._v(", with "),s("code",[t._v("SchemaComparisonChange")]),t._v(" being a sealed trait representing the various kinds of changes. "),s("code",[t._v("SchemaComparisonChange#breaking")]),t._v(" indicates if the change is breaking, such as removing a field or a type. "),s("code",[t._v("SchemaComparisonChange#toString")]),t._v(" will return a nice description of the change.")]),t._v(" "),s("p",[t._v("The following example will compare the schema obtained by Caliban with a schema defined in a string and print the differences.")]),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("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("GraphQL"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("graphQL\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("RootResolver\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("tools"),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("UIO\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// schema from String")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schema"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token triple-quoted-string string"}},[t._v('"""\n type Hero {\n name(pad: Int!): String!\n nick: String!\n bday: Int\n }\n \n type Query {\n hero: Hero!\n }"""')]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// schema from Caliban")]),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(" NameArgs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("pad"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),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(" Hero"),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(" NameArgs "),s("span",{pre:!0,attrs:{class:"token keyword"}},[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(" nick"),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(" bday"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),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 keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Query"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("hero"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Hero"),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("(")]),t._v("RootResolver"),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("Hero"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_ "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"nick"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),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(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\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 diff "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" SchemaComparison"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("compare"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("SchemaLoader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromString"),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(" SchemaLoader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromCaliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("api"),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 keyword"}},[t._v("<-")]),t._v(" UIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("println"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("diff"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mkString"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"\\n"')]),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("\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("(")]),s("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([[19],{404:function(t,a,s){"use strict";s.r(a);var n=s(54),e=Object(n.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"tools"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#tools"}},[t._v("#")]),t._v(" Tools")]),t._v(" "),s("p",[t._v("Caliban comes with a module called "),s("code",[t._v("caliban-tools")]),t._v(" that exposes some useful features:")]),t._v(" "),s("ul",[s("li",[t._v("all the code generation features from "),s("code",[t._v("caliban-codegen-sbt")]),t._v(", so that you can use them without sbt: see "),s("code",[t._v("caliban.tools.Codegen")]),t._v(".")]),t._v(" "),s("li",[t._v("a client for GraphQL introspection: see "),s("code",[t._v("caliban.tools.IntrospectionClient")]),t._v(".")]),t._v(" "),s("li",[t._v("utilities for "),s("RouterLink",{attrs:{to:"/docs/stitching.html"}},[t._v("stitching GraphQL schemas")]),t._v(".")],1),t._v(" "),s("li",[t._v("a way to compare GraphQL schemas, whether they come from Caliban or a remote server, see below.")])]),t._v(" "),s("h2",{attrs:{id:"dependency"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#dependency"}},[t._v("#")]),t._v(" Dependency")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v('libraryDependencies += "com.github.ghostdogpr" %% "caliban-tools" % "1.2.1"\n')])])]),s("h2",{attrs:{id:"schema-comparison"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#schema-comparison"}},[t._v("#")]),t._v(" Schema comparison")]),t._v(" "),s("p",[t._v("The object "),s("code",[t._v("caliban.tools.SchemaComparison")]),t._v(" exposes a "),s("code",[t._v("compare")]),t._v(" function that compares 2 schemas from different origins. It takes 2 "),s("code",[t._v("SchemaLoader")]),t._v(" as arguments, which you can build with one of the following constructors:")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("fromCaliban")]),t._v(": pass your "),s("code",[t._v("GraphQL")]),t._v(" object from Caliban")]),t._v(" "),s("li",[s("code",[t._v("fromFile")]),t._v(": pass the path to a file containing your schema in the GraphQL IDL")]),t._v(" "),s("li",[s("code",[t._v("fromString")]),t._v(": pass a string containing your schema in the GraphQL IDL")]),t._v(" "),s("li",[s("code",[t._v("fromIntrospection")]),t._v(": pass the URL of a GraphQL server supporting introspection")])]),t._v(" "),s("p",[t._v("The output of "),s("code",[t._v("compare")]),t._v(" is a "),s("code",[t._v("Task[List[SchemaComparisonChange]]")]),t._v(", with "),s("code",[t._v("SchemaComparisonChange")]),t._v(" being a sealed trait representing the various kinds of changes. "),s("code",[t._v("SchemaComparisonChange#breaking")]),t._v(" indicates if the change is breaking, such as removing a field or a type. "),s("code",[t._v("SchemaComparisonChange#toString")]),t._v(" will return a nice description of the change.")]),t._v(" "),s("p",[t._v("The following example will compare the schema obtained by Caliban with a schema defined in a string and print the differences.")]),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("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("GraphQL"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("graphQL\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("RootResolver\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("tools"),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("UIO\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// schema from String")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schema"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token triple-quoted-string string"}},[t._v('"""\n type Hero {\n name(pad: Int!): String!\n nick: String!\n bday: Int\n }\n \n type Query {\n hero: Hero!\n }"""')]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// schema from Caliban")]),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(" NameArgs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("pad"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),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(" Hero"),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(" NameArgs "),s("span",{pre:!0,attrs:{class:"token keyword"}},[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(" nick"),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(" bday"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),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 keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Query"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("hero"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Hero"),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("(")]),t._v("RootResolver"),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("Hero"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_ "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"nick"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),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(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\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 diff "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" SchemaComparison"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("compare"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("SchemaLoader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromString"),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(" SchemaLoader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromCaliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("api"),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 keyword"}},[t._v("<-")]),t._v(" UIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("println"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("diff"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mkString"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"\\n"')]),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("\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("(")]),s("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/2.942dda74.js b/docs/assets/js/2.942dda74.js new file mode 100644 index 0000000000..75798843ec --- /dev/null +++ b/docs/assets/js/2.942dda74.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{333:function(t,e,n){"use strict";n.d(e,"d",(function(){return i})),n.d(e,"a",(function(){return a})),n.d(e,"i",(function(){return s})),n.d(e,"f",(function(){return u})),n.d(e,"g",(function(){return l})),n.d(e,"h",(function(){return c})),n.d(e,"b",(function(){return h})),n.d(e,"e",(function(){return f})),n.d(e,"k",(function(){return p})),n.d(e,"l",(function(){return d})),n.d(e,"c",(function(){return v})),n.d(e,"j",(function(){return m}));n(29),n(82),n(334),n(108),n(336),n(190),n(81),n(111),n(6),n(112),n(34),n(113),n(183);var i=/#.*$/,r=/\.(md|html)$/,a=/\/$/,s=/^[a-z]+:/i;function o(t){return decodeURI(t).replace(i,"").replace(r,"")}function u(t){return s.test(t)}function l(t){return/^mailto:/.test(t)}function c(t){return/^tel:/.test(t)}function h(t){if(u(t))return t;var e=t.match(i),n=e?e[0]:"",r=o(t);return a.test(r)?t:r+".html"+n}function f(t,e){var n=decodeURIComponent(t.hash),r=function(t){var e=t.match(i);if(e)return e[0]}(e);return(!r||n===r)&&o(t.path)===o(e)}function p(t,e,n){if(u(e))return{type:"external",path:e};n&&(e=function(t,e,n){var i=t.charAt(0);if("/"===i)return t;if("?"===i||"#"===i)return e+t;var r=e.split("/");n&&r[r.length-1]||r.pop();for(var a=t.replace(/^\//,"").split("/"),s=0;s3&&void 0!==arguments[3]?arguments[3]:1;if("string"==typeof e)return p(n,e,i);if(Array.isArray(e))return Object.assign(p(n,e[0],i),{title:e[1]});var a=e.children||[];return 0===a.length&&e.path?Object.assign(p(n,e.path,i),{title:e.title}):{type:"group",path:e.path,title:e.title,sidebarDepth:e.sidebarDepth,initialOpenGroupIndex:e.initialOpenGroupIndex,children:a.map((function(e){return t(e,n,i,r+1)})),collapsable:!1!==e.collapsable}}(t,r,l)})):[]}return[]}function g(t){var e=v(t.headers||[]);return[{type:"group",collapsable:!1,title:t.title,path:null,children:e.map((function(e){return{type:"auto",title:e.title,basePath:t.path,path:t.path+"#"+e.slug,children:e.children||[]}}))}]}function v(t){var e;return(t=t.map((function(t){return Object.assign({},t)}))).forEach((function(t){2===t.level?e=t:e&&(e.children||(e.children=[])).push(t)})),t.filter((function(t){return 2===t.level}))}function m(t){return Object.assign(t,{type:t.items&&t.items.length?"links":"link"})}},334:function(t,e,n){"use strict";var i=n(9),r=n(187),a=n(8),s=n(83),o=n(21),u=n(30),l=n(55),c=n(188),h=n(189);r("match",(function(t,e,n){return[function(e){var n=u(this),r=null==e?void 0:l(e,t);return r?i(r,e,n):new RegExp(e)[t](o(n))},function(t){var i=a(this),r=o(t),u=n(e,i,r);if(u.done)return u.value;if(!i.global)return h(i,r);var l=i.unicode;i.lastIndex=0;for(var f,p=[],d=0;null!==(f=h(i,r));){var g=o(f[0]);p[d]=g,""===g&&(i.lastIndex=c(r,s(i.lastIndex),l)),d++}return 0===d?null:p}]}))},335:function(t,e){t.exports="\t\n\v\f\r Β αš€β€€β€β€‚β€ƒβ€„β€…β€†β€‡β€ˆβ€‰β€Šβ€―βŸγ€€\u2028\u2029\ufeff"},336:function(t,e,n){"use strict";var i=n(36),r=n(9),a=n(2),s=n(187),o=n(184),u=n(8),l=n(30),c=n(116),h=n(188),f=n(83),p=n(21),d=n(55),g=n(37),v=n(189),m=n(86),b=n(182),k=n(3),_=b.UNSUPPORTED_Y,x=Math.min,y=[].push,C=a(/./.exec),$=a(y),L=a("".slice);s("split",(function(t,e,n){var a;return a="c"=="abbc".split(/(b)*/)[1]||4!="test".split(/(?:)/,-1).length||2!="ab".split(/(?:ab)*/).length||4!=".".split(/(.?)(.?)/).length||".".split(/()()/).length>1||"".split(/.?/).length?function(t,n){var a=p(l(this)),s=void 0===n?4294967295:n>>>0;if(0===s)return[];if(void 0===t)return[a];if(!o(t))return r(e,a,t,s);for(var u,c,h,f=[],d=(t.ignoreCase?"i":"")+(t.multiline?"m":"")+(t.unicode?"u":"")+(t.sticky?"y":""),v=0,b=new RegExp(t.source,d+"g");(u=r(m,b,a))&&!((c=b.lastIndex)>v&&($(f,L(a,v,u.index)),u.length>1&&u.index=s));)b.lastIndex===u.index&&b.lastIndex++;return v===a.length?!h&&C(b,"")||$(f,""):$(f,L(a,v)),f.length>s?g(f,0,s):f}:"0".split(void 0,0).length?function(t,n){return void 0===t&&0===n?[]:r(e,this,t,n)}:e,[function(e,n){var i=l(this),s=null==e?void 0:d(e,t);return s?r(s,e,i,n):r(a,p(i),e,n)},function(t,i){var r=u(this),s=p(t),o=n(a,r,s,i,a!==e);if(o.done)return o.value;var l=c(r,RegExp),d=r.unicode,g=(r.ignoreCase?"i":"")+(r.multiline?"m":"")+(r.unicode?"u":"")+(_?"g":"y"),m=new l(_?"^(?:"+r.source+")":r,g),b=void 0===i?4294967295:i>>>0;if(0===b)return[];if(0===s.length)return null===v(m,s)?[s]:[];for(var k=0,y=0,C=[];y@^][^\s!#%&*+<=>@^]*>/,N=/a/g,A=/a/g,D=new L(N)!==N,U=g.UNSUPPORTED_Y,H=i&&(!D||U||y||C||m((function(){return A[$]=!1,L(N)!=N||L(A)==A||"/a/i"!=L(N,"i")})));if(s("RegExp",H)){for(var W=function(t,e){var n,i,r,a,s,l,c=h(w,this),d=f(t),g=void 0===e,v=[],m=t;if(!c&&d&&g&&t.constructor===W)return t;if((d||h(w,t))&&(t=t.source,g&&(e="flags"in m?m.flags:S(m))),t=void 0===t?"":p(t),e=void 0===e?"":p(e),m=t,y&&"dotAll"in N&&(i=!!e&&R(e,"s")>-1)&&(e=j(e,/s/g,"")),n=e,U&&"sticky"in N&&(r=!!e&&R(e,"y")>-1)&&(e=j(e,/y/g,"")),C&&(t=(a=function(t){for(var e,n=t.length,i=0,r="",a=[],s={},o=!1,u=!1,l=0,c="";i<=n;i++){if("\\"===(e=E(t,i)))e+=E(t,++i);else if("]"===e)o=!1;else if(!o)switch(!0){case"["===e:o=!0;break;case"("===e:I(T,P(t,i+1))&&(i+=2,u=!0),r+=e,l++;continue;case">"===e&&u:if(""===c||b(s,c))throw new O("Invalid capture group name");s[c]=!0,a[a.length]=[c,l],u=!1,c="";continue}u?c+=e:r+=e}return[r,a]}(t))[0],v=a[1]),s=o(L(t,e),c?this:w,W),(i||r||v.length)&&(l=k(s),i&&(l.dotAll=!0,l.raw=W(function(t){for(var e,n=t.length,i=0,r="",a=!1;i<=n;i++)"\\"!==(e=E(t,i))?a||"."!==e?("["===e?a=!0:"]"===e&&(a=!1),r+=e):r+="[\\s\\S]":r+=e+E(t,++i);return r}(t),n)),r&&(l.sticky=!0),v.length&&(l.groups=v)),t!==m)try{u(s,"source",""===m?"(?:)":m)}catch(t){}return s},G=function(t){t in W||l(W,t,{configurable:!0,get:function(){return L[t]},set:function(e){L[t]=e}})},B=c(L),M=0;B.length>M;)G(B[M++]);w.constructor=W,W.prototype=w,v(r,"RegExp",W)}_("RegExp")},341:function(t,e,n){var i=n(0),r=n(11),a=n(186),s=n(22),o=n(12).f,u=n(31).get,l=RegExp.prototype,c=i.TypeError;r&&a&&o(l,"dotAll",{configurable:!0,get:function(){if(this!==l){if("RegExp"===s(this))return!!u(this).dotAll;throw c("Incompatible receiver, RegExp required")}}})},342:function(t,e,n){var i=n(0),r=n(11),a=n(182).UNSUPPORTED_Y,s=n(22),o=n(12).f,u=n(31).get,l=RegExp.prototype,c=i.TypeError;r&&a&&o(l,"sticky",{configurable:!0,get:function(){if(this!==l){if("RegExp"===s(this))return!!u(this).sticky;throw c("Incompatible receiver, RegExp required")}}})},343:function(t,e,n){"use strict";var i=n(2),r=n(84).PROPER,a=n(17),s=n(8),o=n(35),u=n(21),l=n(3),c=n(185),h=RegExp.prototype,f=h.toString,p=i(c),d=l((function(){return"/a/b"!=f.call({source:"a",flags:"b"})})),g=r&&"toString"!=f.name;(d||g)&&a(RegExp.prototype,"toString",(function(){var t=s(this),e=u(t.source),n=t.flags;return"/"+e+"/"+u(void 0===n&&o(h,t)&&!("flags"in h)?p(t):n)}),{unsafe:!0})},344:function(t,e,n){},345:function(t,e,n){},346:function(t,e,n){},347:function(t,e,n){},348:function(t,e,n){},349:function(t,e,n){},350:function(t,e){t.exports=function(t){return null==t}},351:function(t,e,n){},352:function(t,e,n){},353:function(t,e,n){},354:function(t,e,n){},355:function(t,e,n){},356:function(t,e,n){},360:function(t,e,n){"use strict";n.r(e);n(109),n(6);var i=n(333),r={name:"SidebarGroup",components:{DropdownTransition:n(361).a},props:["item","open","collapsable","depth"],beforeCreate:function(){this.$options.components.SidebarLinks=n(360).default},methods:{isActive:i.e}},a=(n(381),n(54)),s=Object(a.a)(r,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("section",{staticClass:"sidebar-group",class:[{collapsable:t.collapsable,"is-sub-group":0!==t.depth},"depth-"+t.depth]},[t.item.path?n("RouterLink",{staticClass:"sidebar-heading clickable",class:{open:t.open,active:t.isActive(t.$route,t.item.path)},attrs:{to:t.item.path},nativeOn:{click:function(e){return t.$emit("toggle")}}},[n("span",[t._v(t._s(t.item.title))]),t._v(" "),t.collapsable?n("span",{staticClass:"arrow",class:t.open?"down":"right"}):t._e()]):n("p",{staticClass:"sidebar-heading",class:{open:t.open},on:{click:function(e){return t.$emit("toggle")}}},[n("span",[t._v(t._s(t.item.title))]),t._v(" "),t.collapsable?n("span",{staticClass:"arrow",class:t.open?"down":"right"}):t._e()]),t._v(" "),n("DropdownTransition",[t.open||!t.collapsable?n("SidebarLinks",{staticClass:"sidebar-group-items",attrs:{items:t.item.children,"sidebar-depth":t.item.sidebarDepth,"initial-open-group-index":t.item.initialOpenGroupIndex,depth:t.depth+1}}):t._e()],1)],1)}),[],!1,null,null,null).exports;n(382),n(29),n(108),n(81);function o(t,e,n,i,r){var a={props:{to:e,activeClass:"",exactActiveClass:""},class:{active:i,"sidebar-link":!0}};return r>2&&(a.style={"padding-left":r+"rem"}),t("RouterLink",a,n)}function u(t,e,n,r,a){var s=arguments.length>5&&void 0!==arguments[5]?arguments[5]:1;return!e||s>a?null:t("ul",{class:"sidebar-sub-headers"},e.map((function(e){var l=Object(i.e)(r,n+"#"+e.slug);return t("li",{class:"sidebar-sub-header"},[o(t,n+"#"+e.slug,e.title,l,e.level-1),u(t,e.children,n,r,a,s+1)])})))}var l={functional:!0,props:["item","sidebarDepth"],render:function(t,e){var n=e.parent,r=n.$page,a=(n.$site,n.$route),s=n.$themeConfig,l=n.$themeLocaleConfig,c=e.props,h=c.item,f=c.sidebarDepth,p=Object(i.e)(a,h.path),d="auto"===h.type?p||h.children.some((function(t){return Object(i.e)(a,h.basePath+"#"+t.slug)})):p,g="external"===h.type?function(t,e,n){return t("a",{attrs:{href:e,target:"_blank",rel:"noopener noreferrer"},class:{"sidebar-link":!0}},[n,t("OutboundLink")])}(t,h.path,h.title||h.path):o(t,h.path,h.title||h.path,d),v=[r.frontmatter.sidebarDepth,f,l.sidebarDepth,s.sidebarDepth,1].find((function(t){return void 0!==t})),m=l.displayAllHeaders||s.displayAllHeaders;return"auto"===h.type?[g,u(t,h.children,h.basePath,a,v)]:(d||m)&&h.headers&&!i.d.test(h.path)?[g,u(t,Object(i.c)(h.headers),h.path,a,v)]:g}};n(383);function c(t,e){if("group"===e.type){var n=e.path&&Object(i.e)(t,e.path),r=e.children.some((function(e){return"group"===e.type?c(t,e):"page"===e.type&&Object(i.e)(t,e.path)}));return n||r}return!1}var h={name:"SidebarLinks",components:{SidebarGroup:s,SidebarLink:Object(a.a)(l,void 0,void 0,!1,null,null,null).exports},props:["items","depth","sidebarDepth","initialOpenGroupIndex"],data:function(){return{openGroupIndex:this.initialOpenGroupIndex||0}},watch:{$route:function(){this.refreshIndex()}},created:function(){this.refreshIndex()},methods:{refreshIndex:function(){var t=function(t,e){for(var n=0;n-1&&(this.openGroupIndex=t)},toggleGroup:function(t){this.openGroupIndex=t===this.openGroupIndex?-1:t},isActive:function(t){return Object(i.e)(this.$route,t.regularPath)}}},f=Object(a.a)(h,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.items.length?n("ul",{staticClass:"sidebar-links"},t._l(t.items,(function(e,i){return n("li",{key:i},["group"===e.type?n("SidebarGroup",{attrs:{item:e,open:i===t.openGroupIndex,collapsable:e.collapsable||e.collapsible,depth:t.depth},on:{toggle:function(e){return t.toggleGroup(i)}}}):n("SidebarLink",{attrs:{"sidebar-depth":t.sidebarDepth,item:e}})],1)})),0):t._e()}),[],!1,null,null,null);e.default=f.exports},361:function(t,e,n){"use strict";var i={name:"DropdownTransition",methods:{setHeight:function(t){t.style.height=t.scrollHeight+"px"},unsetHeight:function(t){t.style.height=""}}},r=(n(373),n(54)),a=Object(r.a)(i,(function(){var t=this.$createElement;return(this._self._c||t)("transition",{attrs:{name:"dropdown"},on:{enter:this.setHeight,"after-enter":this.unsetHeight,"before-leave":this.setHeight}},[this._t("default")],2)}),[],!1,null,null,null);e.a=a.exports},362:function(t,e,n){"use strict";var i=n(1),r=n(363);i({target:"String",proto:!0,forced:n(364)("link")},{link:function(t){return r(this,"a","href",t)}})},363:function(t,e,n){var i=n(2),r=n(30),a=n(21),s=/"/g,o=i("".replace);t.exports=function(t,e,n,i){var u=a(r(t)),l="<"+e;return""!==n&&(l+=" "+n+'="'+o(a(i),s,""")+'"'),l+">"+u+""}},364:function(t,e,n){var i=n(3);t.exports=function(t){return i((function(){var e=""[t]('"');return e!==e.toLowerCase()||e.split('"').length>3}))}},365:function(t,e,n){"use strict";n(337)},366:function(t,e,n){var i=n(1),r=n(367);i({global:!0,forced:parseInt!=r},{parseInt:r})},367:function(t,e,n){var i=n(0),r=n(3),a=n(2),s=n(21),o=n(338).trim,u=n(335),l=i.parseInt,c=i.Symbol,h=c&&c.iterator,f=/^[+-]?0x/i,p=a(f.exec),d=8!==l(u+"08")||22!==l(u+"0x16")||h&&!r((function(){l(Object(h))}));t.exports=d?function(t,e){var n=o(s(t));return l(n,e>>>0||(p(f,n)?16:10))}:l},368:function(t,e,n){var i=n(84).PROPER,r=n(3),a=n(335);t.exports=function(t){return r((function(){return!!a[t]()||"β€‹Β…α Ž"!=="β€‹Β…α Ž"[t]()||i&&a[t].name!==t}))}},369:function(t,e,n){var i=n(5),r=n(7),a=n(85);t.exports=function(t,e,n){var s,o;return a&&i(s=e.constructor)&&s!==n&&r(o=s.prototype)&&o!==n.prototype&&a(t,o),t}},370:function(t,e,n){"use strict";var i,r=n(1),a=n(2),s=n(32).f,o=n(83),u=n(21),l=n(117),c=n(30),h=n(118),f=n(23),p=a("".endsWith),d=a("".slice),g=Math.min,v=h("endsWith");r({target:"String",proto:!0,forced:!!(f||v||(i=s(String.prototype,"endsWith"),!i||i.writable))&&!v},{endsWith:function(t){var e=u(c(this));l(t);var n=arguments.length>1?arguments[1]:void 0,i=e.length,r=void 0===n?i:g(o(n),i),a=u(t);return p?p(e,a,r):d(e,r-a.length,r)===a}})},371:function(t,e,n){"use strict";n(344)},372:function(t,e,n){"use strict";n(345)},373:function(t,e,n){"use strict";n(346)},374:function(t,e,n){"use strict";n(347)},375:function(t,e,n){"use strict";n(348)},376:function(t,e,n){"use strict";n(349)},377:function(t,e,n){"use strict";n(351)},378:function(t,e,n){var i=n(39),r=n(18),a=n(33);t.exports=function(t){return"string"==typeof t||!r(t)&&a(t)&&"[object String]"==i(t)}},379:function(t,e,n){"use strict";n(352)},380:function(t,e,n){"use strict";n(353)},381:function(t,e,n){"use strict";n(354)},382:function(t,e,n){"use strict";var i=n(1),r=n(38).find,a=n(114),s=!0;"find"in[]&&Array(1).find((function(){s=!1})),i({target:"Array",proto:!0,forced:s},{find:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0)}}),a("find")},383:function(t,e,n){"use strict";n(355)},384:function(t,e,n){"use strict";n(356)},388:function(t,e,n){"use strict";n.r(e);n(362),n(109),n(6),n(110);var i=n(333),r={name:"NavLink",props:{item:{required:!0}},computed:{link:function(){return Object(i.b)(this.item.link)},exact:function(){var t=this;return this.$site.locales?Object.keys(this.$site.locales).some((function(e){return e===t.link})):"/"===this.link},isNonHttpURI:function(){return Object(i.g)(this.link)||Object(i.h)(this.link)},isBlankTarget:function(){return"_blank"===this.target},isInternal:function(){return!Object(i.f)(this.link)&&!this.isBlankTarget},target:function(){return this.isNonHttpURI?null:this.item.target?this.item.target:Object(i.f)(this.link)?"_blank":""},rel:function(){return this.isNonHttpURI||!1===this.item.rel?null:this.item.rel?this.item.rel:this.isBlankTarget?"noopener noreferrer":null}},methods:{focusoutAction:function(){this.$emit("focusout")}}},a=n(54),s=Object(a.a)(r,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.isInternal?n("RouterLink",{staticClass:"nav-link",attrs:{to:t.link,exact:t.exact},nativeOn:{focusout:function(e){return t.focusoutAction.apply(null,arguments)}}},[t._v("\n "+t._s(t.item.text)+"\n")]):n("a",{staticClass:"nav-link external",attrs:{href:t.link,target:t.target,rel:t.rel},on:{focusout:t.focusoutAction}},[t._v("\n "+t._s(t.item.text)+"\n "),t.isBlankTarget?n("OutboundLink"):t._e()],1)}),[],!1,null,null,null).exports,o={name:"Home",components:{NavLink:s},computed:{data:function(){return this.$page.frontmatter},actionLink:function(){return{link:this.data.actionLink,text:this.data.actionText}}}},u=(n(365),Object(a.a)(o,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("main",{staticClass:"home",attrs:{"aria-labelledby":null!==t.data.heroText?"main-title":null}},[n("header",{staticClass:"hero"},[t.data.heroImage?n("img",{attrs:{src:t.$withBase(t.data.heroImage),alt:t.data.heroAlt||"hero"}}):t._e(),t._v(" "),null!==t.data.heroText?n("h1",{attrs:{id:"main-title"}},[t._v("\n "+t._s(t.data.heroText||t.$title||"Hello")+"\n ")]):t._e(),t._v(" "),null!==t.data.tagline?n("p",{staticClass:"description"},[t._v("\n "+t._s(t.data.tagline||t.$description||"Welcome to your VuePress site")+"\n ")]):t._e(),t._v(" "),t.data.actionText&&t.data.actionLink?n("p",{staticClass:"action"},[n("NavLink",{staticClass:"action-button",attrs:{item:t.actionLink}})],1):t._e()]),t._v(" "),t.data.features&&t.data.features.length?n("div",{staticClass:"features"},t._l(t.data.features,(function(e,i){return n("div",{key:i,staticClass:"feature"},[n("h2",[t._v(t._s(e.title))]),t._v(" "),n("p",[t._v(t._s(e.details))])])})),0):t._e(),t._v(" "),n("Content",{staticClass:"theme-default-content custom"}),t._v(" "),t.data.footer?n("div",{staticClass:"footer"},[t._v("\n "+t._s(t.data.footer)+"\n ")]):t._e()],1)}),[],!1,null,null,null).exports),l=(n(366),n(339),n(183),n(113),n(34),n(29),n(334),n(193),n(194),n(190),n(82),n(340),n(341),n(342),n(343),n(81),n(336),n(108),n(370),n(196)),c=n.n(l),h=function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,i=c()(e,"title","");return c()(e,"frontmatter.tags")&&(i+=" ".concat(e.frontmatter.tags.join(" "))),n&&(i+=" ".concat(n)),f(t,i)},f=function(t,e){var n=function(t){return t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&")},i=new RegExp("[^\0-]"),r=t.split(/\s+/g).map((function(t){return t.trim()})).filter((function(t){return!!t}));if(i.test(t))return r.some((function(t){return e.toLowerCase().indexOf(t)>-1}));var a=t.endsWith(" ");return new RegExp(r.map((function(t,e){return r.length!==e+1||a?"(?=.*\\b".concat(n(t),"\\b)"):"(?=.*\\b".concat(n(t),")")})).join("")+".+","gi").test(e)},p={name:"SearchBox",data:function(){return{query:"",focused:!1,focusIndex:0,placeholder:void 0}},computed:{showSuggestions:function(){return this.focused&&this.suggestions&&this.suggestions.length},suggestions:function(){var t=this.query.trim().toLowerCase();if(t){for(var e=this.$site.pages,n=this.$site.themeConfig.searchMaxSuggestions||5,i=this.$localePath,r=[],a=0;a=n);a++){var s=e[a];if(this.getPageLocalePath(s)===i&&this.isSearchable(s))if(h(t,s))r.push(s);else if(s.headers)for(var o=0;o=n);o++){var u=s.headers[o];u.title&&h(t,s,u.title)&&r.push(Object.assign({},s,{path:s.path+"#"+u.slug,header:u}))}}return r}},alignRight:function(){return(this.$site.themeConfig.nav||[]).length+(this.$site.repo?1:0)<=2}},mounted:function(){this.placeholder=this.$site.themeConfig.searchPlaceholder||"",document.addEventListener("keydown",this.onHotkey)},beforeDestroy:function(){document.removeEventListener("keydown",this.onHotkey)},methods:{getPageLocalePath:function(t){for(var e in this.$site.locales||{})if("/"!==e&&0===t.path.indexOf(e))return e;return"/"},isSearchable:function(t){var e=null;return null===e||(e=Array.isArray(e)?e:new Array(e)).filter((function(e){return t.path.match(e)})).length>0},onHotkey:function(t){t.srcElement===document.body&&["s","/"].includes(t.key)&&(this.$refs.input.focus(),t.preventDefault())},onUp:function(){this.showSuggestions&&(this.focusIndex>0?this.focusIndex--:this.focusIndex=this.suggestions.length-1)},onDown:function(){this.showSuggestions&&(this.focusIndex "+t._s(e.header.title))]):t._e()])])})),0):t._e()])}),[],!1,null,null,null).exports),g=(n(372),Object(a.a)({},(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"sidebar-button",on:{click:function(e){return t.$emit("toggle-sidebar")}}},[n("svg",{staticClass:"icon",attrs:{xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",role:"img",viewBox:"0 0 448 512"}},[n("path",{attrs:{fill:"currentColor",d:"M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"}})])])}),[],!1,null,null,null).exports),v=n(52),m=(n(195),n(361)),b=n(197),k=n.n(b),_={name:"DropdownLink",components:{NavLink:s,DropdownTransition:m.a},props:{item:{required:!0}},data:function(){return{open:!1}},computed:{dropdownAriaLabel:function(){return this.item.ariaLabel||this.item.text}},watch:{$route:function(){this.open=!1}},methods:{setOpen:function(t){this.open=t},isLastItemOfArray:function(t,e){return k()(e)===t},handleDropdown:function(){0===event.detail&&this.setOpen(!this.open)}}},x=(n(374),{name:"NavLinks",components:{NavLink:s,DropdownLink:Object(a.a)(_,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"dropdown-wrapper",class:{open:t.open}},[n("button",{staticClass:"dropdown-title",attrs:{type:"button","aria-label":t.dropdownAriaLabel},on:{click:t.handleDropdown}},[n("span",{staticClass:"title"},[t._v(t._s(t.item.text))]),t._v(" "),n("span",{staticClass:"arrow down"})]),t._v(" "),n("button",{staticClass:"mobile-dropdown-title",attrs:{type:"button","aria-label":t.dropdownAriaLabel},on:{click:function(e){return t.setOpen(!t.open)}}},[n("span",{staticClass:"title"},[t._v(t._s(t.item.text))]),t._v(" "),n("span",{staticClass:"arrow",class:t.open?"down":"right"})]),t._v(" "),n("DropdownTransition",[n("ul",{directives:[{name:"show",rawName:"v-show",value:t.open,expression:"open"}],staticClass:"nav-dropdown"},t._l(t.item.items,(function(e,i){return n("li",{key:e.link||i,staticClass:"dropdown-item"},["links"===e.type?n("h4",[t._v("\n "+t._s(e.text)+"\n ")]):t._e(),t._v(" "),"links"===e.type?n("ul",{staticClass:"dropdown-subitem-wrapper"},t._l(e.items,(function(i){return n("li",{key:i.link,staticClass:"dropdown-subitem"},[n("NavLink",{attrs:{item:i},on:{focusout:function(n){t.isLastItemOfArray(i,e.items)&&t.isLastItemOfArray(e,t.item.items)&&t.setOpen(!1)}}})],1)})),0):n("NavLink",{attrs:{item:e},on:{focusout:function(n){t.isLastItemOfArray(e,t.item.items)&&t.setOpen(!1)}}})],1)})),0)])],1)}),[],!1,null,null,null).exports},computed:{userNav:function(){return this.$themeLocaleConfig.nav||this.$site.themeConfig.nav||[]},nav:function(){var t=this,e=this.$site.locales;if(e&&Object.keys(e).length>1){var n=this.$page.path,i=this.$router.options.routes,r=this.$site.themeConfig.locales||{},a={text:this.$themeLocaleConfig.selectText||"Languages",ariaLabel:this.$themeLocaleConfig.ariaLabel||"Select language",items:Object.keys(e).map((function(a){var s,o=e[a],u=r[a]&&r[a].label||o.lang;return o.lang===t.$lang?s=n:(s=n.replace(t.$localeConfig.path,a),i.some((function(t){return t.path===s}))||(s=a)),{text:u,link:s}}))};return[].concat(Object(v.a)(this.userNav),[a])}return this.userNav},userLinks:function(){return(this.nav||[]).map((function(t){return Object.assign(Object(i.j)(t),{items:(t.items||[]).map(i.j)})}))},repoLink:function(){var t=this.$site.themeConfig.repo;return t?/^https?:/.test(t)?t:"https://github.com/".concat(t):null},repoLabel:function(){if(this.repoLink){if(this.$site.themeConfig.repoLabel)return this.$site.themeConfig.repoLabel;for(var t=this.repoLink.match(/^https?:\/\/[^/]+/)[0],e=["GitHub","GitLab","Bitbucket"],n=0;nMath.abs(n)&&Math.abs(e)>40&&(e>0&&this.touchStart.x<=80?this.toggleSidebar(!0):this.toggleSidebar(!1))}}}),G=Object(a.a)(W,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"theme-container",class:t.pageClasses,on:{touchstart:t.onTouchStart,touchend:t.onTouchEnd}},[t.shouldShowNavbar?n("Navbar",{on:{"toggle-sidebar":t.toggleSidebar}}):t._e(),t._v(" "),n("div",{staticClass:"sidebar-mask",on:{click:function(e){return t.toggleSidebar(!1)}}}),t._v(" "),n("Sidebar",{attrs:{items:t.sidebarItems},on:{"toggle-sidebar":t.toggleSidebar},scopedSlots:t._u([{key:"top",fn:function(){return[t._t("sidebar-top")]},proxy:!0},{key:"bottom",fn:function(){return[t._t("sidebar-bottom")]},proxy:!0}],null,!0)}),t._v(" "),t.$page.frontmatter.home?n("Home"):n("Page",{attrs:{"sidebar-items":t.sidebarItems},scopedSlots:t._u([{key:"top",fn:function(){return[t._t("page-top")]},proxy:!0},{key:"bottom",fn:function(){return[t._t("page-bottom")]},proxy:!0}],null,!0)})],1)}),[],!1,null,null,null);e.default=G.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/2.caf3e0bc.js b/docs/assets/js/2.caf3e0bc.js deleted file mode 100644 index c85bcef119..0000000000 --- a/docs/assets/js/2.caf3e0bc.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{323:function(t,e,n){"use strict";n.d(e,"d",(function(){return i})),n.d(e,"a",(function(){return a})),n.d(e,"i",(function(){return s})),n.d(e,"f",(function(){return u})),n.d(e,"g",(function(){return l})),n.d(e,"h",(function(){return c})),n.d(e,"b",(function(){return h})),n.d(e,"e",(function(){return p})),n.d(e,"k",(function(){return f})),n.d(e,"l",(function(){return d})),n.d(e,"c",(function(){return v})),n.d(e,"j",(function(){return m}));n(47),n(76),n(324),n(326),n(182),n(75),n(104),n(105),n(31),n(106),n(175);var i=/#.*$/,r=/\.(md|html)$/,a=/\/$/,s=/^[a-z]+:/i;function o(t){return decodeURI(t).replace(i,"").replace(r,"")}function u(t){return s.test(t)}function l(t){return/^mailto:/.test(t)}function c(t){return/^tel:/.test(t)}function h(t){if(u(t))return t;var e=t.match(i),n=e?e[0]:"",r=o(t);return a.test(r)?t:r+".html"+n}function p(t,e){var n=decodeURIComponent(t.hash),r=function(t){var e=t.match(i);if(e)return e[0]}(e);return(!r||n===r)&&o(t.path)===o(e)}function f(t,e,n){if(u(e))return{type:"external",path:e};n&&(e=function(t,e,n){var i=t.charAt(0);if("/"===i)return t;if("?"===i||"#"===i)return e+t;var r=e.split("/");n&&r[r.length-1]||r.pop();for(var a=t.replace(/^\//,"").split("/"),s=0;s3&&void 0!==arguments[3]?arguments[3]:1;if("string"==typeof e)return f(n,e,i);if(Array.isArray(e))return Object.assign(f(n,e[0],i),{title:e[1]});var a=e.children||[];return 0===a.length&&e.path?Object.assign(f(n,e.path,i),{title:e.title}):{type:"group",path:e.path,title:e.title,sidebarDepth:e.sidebarDepth,initialOpenGroupIndex:e.initialOpenGroupIndex,children:a.map((function(e){return t(e,n,i,r+1)})),collapsable:!1!==e.collapsable}}(t,r,l)})):[]}return[]}function g(t){var e=v(t.headers||[]);return[{type:"group",collapsable:!1,title:t.title,path:null,children:e.map((function(e){return{type:"auto",title:e.title,basePath:t.path,path:t.path+"#"+e.slug,children:e.children||[]}}))}]}function v(t){var e;return(t=t.map((function(t){return Object.assign({},t)}))).forEach((function(t){2===t.level?e=t:e&&(e.children||(e.children=[])).push(t)})),t.filter((function(t){return 2===t.level}))}function m(t){return Object.assign(t,{type:t.items&&t.items.length?"links":"link"})}},324:function(t,e,n){"use strict";var i=n(179),r=n(6),a=n(77),s=n(19),o=n(26),u=n(48),l=n(180),c=n(181);i("match",(function(t,e,n){return[function(e){var n=o(this),i=null==e?void 0:u(e,t);return i?i.call(e,n):new RegExp(e)[t](s(n))},function(t){var i=r(this),o=s(t),u=n(e,i,o);if(u.done)return u.value;if(!i.global)return c(i,o);var h=i.unicode;i.lastIndex=0;for(var p,f=[],d=0;null!==(p=c(i,o));){var g=s(p[0]);f[d]=g,""===g&&(i.lastIndex=l(o,a(i.lastIndex),h)),d++}return 0===d?null:f}]}))},325:function(t,e){t.exports="\t\n\v\f\r Β αš€β€€β€β€‚β€ƒβ€„β€…β€†β€‡β€ˆβ€‰β€Šβ€―βŸγ€€\u2028\u2029\ufeff"},326:function(t,e,n){"use strict";var i=n(179),r=n(176),a=n(6),s=n(26),o=n(109),u=n(180),l=n(77),c=n(19),h=n(48),p=n(181),f=n(80),d=n(178),g=n(1),v=d.UNSUPPORTED_Y,m=[].push,b=Math.min;i("split",(function(t,e,n){var i;return i="c"=="abbc".split(/(b)*/)[1]||4!="test".split(/(?:)/,-1).length||2!="ab".split(/(?:ab)*/).length||4!=".".split(/(.?)(.?)/).length||".".split(/()()/).length>1||"".split(/.?/).length?function(t,n){var i=c(s(this)),a=void 0===n?4294967295:n>>>0;if(0===a)return[];if(void 0===t)return[i];if(!r(t))return e.call(i,t,a);for(var o,u,l,h=[],p=(t.ignoreCase?"i":"")+(t.multiline?"m":"")+(t.unicode?"u":"")+(t.sticky?"y":""),d=0,g=new RegExp(t.source,p+"g");(o=f.call(g,i))&&!((u=g.lastIndex)>d&&(h.push(i.slice(d,o.index)),o.length>1&&o.index=a));)g.lastIndex===o.index&&g.lastIndex++;return d===i.length?!l&&g.test("")||h.push(""):h.push(i.slice(d)),h.length>a?h.slice(0,a):h}:"0".split(void 0,0).length?function(t,n){return void 0===t&&0===n?[]:e.call(this,t,n)}:e,[function(e,n){var r=s(this),a=null==e?void 0:h(e,t);return a?a.call(e,r,n):i.call(c(r),e,n)},function(t,r){var s=a(this),h=c(t),f=n(i,s,h,r,i!==e);if(f.done)return f.value;var d=o(s,RegExp),g=s.unicode,m=(s.ignoreCase?"i":"")+(s.multiline?"m":"")+(s.unicode?"u":"")+(v?"g":"y"),k=new d(v?"^(?:"+s.source+")":s,m),_=void 0===r?4294967295:r>>>0;if(0===_)return[];if(0===h.length)return null===p(k,h)?[h]:[];for(var x=0,C=0,y=[];C@^][^\s!#%&*+<=>@^]*>/,w=/a/g,O=/a/g,S=new y(w)!==w,I=f.UNSUPPORTED_Y,E=i&&(!S||I||_||x||g((function(){return O[C]=!1,y(w)!=w||y(O)==O||"/a/i"!=y(w,"i")})));if(a("RegExp",E)){for(var j=function(t,e){var n,i,r,a,u,l,f=this instanceof j,d=c(t),g=void 0===e,b=[],k=t;if(!f&&d&&g&&t.constructor===j)return t;if((d||t instanceof j)&&(t=t.source,g&&(e="flags"in k?k.flags:p.call(k))),t=void 0===t?"":h(t),e=void 0===e?"":h(e),k=t,_&&"dotAll"in w&&(i=!!e&&e.indexOf("s")>-1)&&(e=e.replace(/s/g,"")),n=e,I&&"sticky"in w&&(r=!!e&&e.indexOf("y")>-1)&&(e=e.replace(/y/g,"")),x&&(t=(a=function(t){for(var e,n=t.length,i=0,r="",a=[],s={},o=!1,u=!1,l=0,c="";i<=n;i++){if("\\"===(e=t.charAt(i)))e+=t.charAt(++i);else if("]"===e)o=!1;else if(!o)switch(!0){case"["===e:o=!0;break;case"("===e:L.test(t.slice(i+1))&&(i+=2,u=!0),r+=e,l++;continue;case">"===e&&u:if(""===c||v(s,c))throw new SyntaxError("Invalid capture group name");s[c]=!0,a.push([c,l]),u=!1,c="";continue}u?c+=e:r+=e}return[r,a]}(t))[0],b=a[1]),u=s(y(t,e),f?this:$,j),(i||r||b.length)&&(l=m(u),i&&(l.dotAll=!0,l.raw=j(function(t){for(var e,n=t.length,i=0,r="",a=!1;i<=n;i++)"\\"!==(e=t.charAt(i))?a||"."!==e?("["===e?a=!0:"]"===e&&(a=!1),r+=e):r+="[\\s\\S]":r+=e+t.charAt(++i);return r}(t),n)),r&&(l.sticky=!0),b.length&&(l.groups=b)),t!==k)try{o(u,"source",""===k?"(?:)":k)}catch(t){}return u},P=function(t){t in j||u(j,t,{configurable:!0,get:function(){return y[t]},set:function(e){y[t]=e}})},R=l(y),A=0;R.length>A;)P(R[A++]);$.constructor=j,j.prototype=$,d(r,"RegExp",j)}b("RegExp")},331:function(t,e,n){"use strict";var i=n(78).PROPER,r=n(14),a=n(6),s=n(19),o=n(1),u=n(177),l=RegExp.prototype,c=l.toString,h=o((function(){return"/a/b"!=c.call({source:"a",flags:"b"})})),p=i&&"toString"!=c.name;(h||p)&&r(RegExp.prototype,"toString",(function(){var t=a(this),e=s(t.source),n=t.flags;return"/"+e+"/"+s(void 0===n&&t instanceof RegExp&&!("flags"in l)?u.call(t):n)}),{unsafe:!0})},332:function(t,e,n){},333:function(t,e,n){},334:function(t,e,n){},335:function(t,e,n){},336:function(t,e,n){},337:function(t,e,n){},338:function(t,e){t.exports=function(t){return null==t}},339:function(t,e,n){},340:function(t,e,n){},341:function(t,e,n){},342:function(t,e,n){},343:function(t,e,n){},344:function(t,e,n){},348:function(t,e,n){"use strict";n.r(e);n(102);var i=n(323),r={name:"SidebarGroup",components:{DropdownTransition:n(349).a},props:["item","open","collapsable","depth"],beforeCreate:function(){this.$options.components.SidebarLinks=n(348).default},methods:{isActive:i.e}},a=(n(369),n(46)),s=Object(a.a)(r,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("section",{staticClass:"sidebar-group",class:[{collapsable:t.collapsable,"is-sub-group":0!==t.depth},"depth-"+t.depth]},[t.item.path?n("RouterLink",{staticClass:"sidebar-heading clickable",class:{open:t.open,active:t.isActive(t.$route,t.item.path)},attrs:{to:t.item.path},nativeOn:{click:function(e){return t.$emit("toggle")}}},[n("span",[t._v(t._s(t.item.title))]),t._v(" "),t.collapsable?n("span",{staticClass:"arrow",class:t.open?"down":"right"}):t._e()]):n("p",{staticClass:"sidebar-heading",class:{open:t.open},on:{click:function(e){return t.$emit("toggle")}}},[n("span",[t._v(t._s(t.item.title))]),t._v(" "),t.collapsable?n("span",{staticClass:"arrow",class:t.open?"down":"right"}):t._e()]),t._v(" "),n("DropdownTransition",[t.open||!t.collapsable?n("SidebarLinks",{staticClass:"sidebar-group-items",attrs:{items:t.item.children,"sidebar-depth":t.item.sidebarDepth,"initial-open-group-index":t.item.initialOpenGroupIndex,depth:t.depth+1}}):t._e()],1)],1)}),[],!1,null,null,null).exports;n(370),n(75);function o(t,e,n,i,r){var a={props:{to:e,activeClass:"",exactActiveClass:""},class:{active:i,"sidebar-link":!0}};return r>2&&(a.style={"padding-left":r+"rem"}),t("RouterLink",a,n)}function u(t,e,n,r,a){var s=arguments.length>5&&void 0!==arguments[5]?arguments[5]:1;return!e||s>a?null:t("ul",{class:"sidebar-sub-headers"},e.map((function(e){var l=Object(i.e)(r,n+"#"+e.slug);return t("li",{class:"sidebar-sub-header"},[o(t,n+"#"+e.slug,e.title,l,e.level-1),u(t,e.children,n,r,a,s+1)])})))}var l={functional:!0,props:["item","sidebarDepth"],render:function(t,e){var n=e.parent,r=n.$page,a=(n.$site,n.$route),s=n.$themeConfig,l=n.$themeLocaleConfig,c=e.props,h=c.item,p=c.sidebarDepth,f=Object(i.e)(a,h.path),d="auto"===h.type?f||h.children.some((function(t){return Object(i.e)(a,h.basePath+"#"+t.slug)})):f,g="external"===h.type?function(t,e,n){return t("a",{attrs:{href:e,target:"_blank",rel:"noopener noreferrer"},class:{"sidebar-link":!0}},[n,t("OutboundLink")])}(t,h.path,h.title||h.path):o(t,h.path,h.title||h.path,d),v=[r.frontmatter.sidebarDepth,p,l.sidebarDepth,s.sidebarDepth,1].find((function(t){return void 0!==t})),m=l.displayAllHeaders||s.displayAllHeaders;return"auto"===h.type?[g,u(t,h.children,h.basePath,a,v)]:(d||m)&&h.headers&&!i.d.test(h.path)?[g,u(t,Object(i.c)(h.headers),h.path,a,v)]:g}};n(371);function c(t,e){if("group"===e.type){var n=e.path&&Object(i.e)(t,e.path),r=e.children.some((function(e){return"group"===e.type?c(t,e):"page"===e.type&&Object(i.e)(t,e.path)}));return n||r}return!1}var h={name:"SidebarLinks",components:{SidebarGroup:s,SidebarLink:Object(a.a)(l,void 0,void 0,!1,null,null,null).exports},props:["items","depth","sidebarDepth","initialOpenGroupIndex"],data:function(){return{openGroupIndex:this.initialOpenGroupIndex||0}},watch:{$route:function(){this.refreshIndex()}},created:function(){this.refreshIndex()},methods:{refreshIndex:function(){var t=function(t,e){for(var n=0;n-1&&(this.openGroupIndex=t)},toggleGroup:function(t){this.openGroupIndex=t===this.openGroupIndex?-1:t},isActive:function(t){return Object(i.e)(this.$route,t.regularPath)}}},p=Object(a.a)(h,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.items.length?n("ul",{staticClass:"sidebar-links"},t._l(t.items,(function(e,i){return n("li",{key:i},["group"===e.type?n("SidebarGroup",{attrs:{item:e,open:i===t.openGroupIndex,collapsable:e.collapsable||e.collapsible,depth:t.depth},on:{toggle:function(e){return t.toggleGroup(i)}}}):n("SidebarLink",{attrs:{"sidebar-depth":t.sidebarDepth,item:e}})],1)})),0):t._e()}),[],!1,null,null,null);e.default=p.exports},349:function(t,e,n){"use strict";var i={name:"DropdownTransition",methods:{setHeight:function(t){t.style.height=t.scrollHeight+"px"},unsetHeight:function(t){t.style.height=""}}},r=(n(361),n(46)),a=Object(r.a)(i,(function(){var t=this.$createElement;return(this._self._c||t)("transition",{attrs:{name:"dropdown"},on:{enter:this.setHeight,"after-enter":this.unsetHeight,"before-leave":this.setHeight}},[this._t("default")],2)}),[],!1,null,null,null);e.a=a.exports},350:function(t,e,n){"use strict";var i=n(0),r=n(351);i({target:"String",proto:!0,forced:n(352)("link")},{link:function(t){return r(this,"a","href",t)}})},351:function(t,e,n){var i=n(26),r=n(19),a=/"/g;t.exports=function(t,e,n,s){var o=r(i(t)),u="<"+e;return""!==n&&(u+=" "+n+'="'+r(s).replace(a,""")+'"'),u+">"+o+""}},352:function(t,e,n){var i=n(1);t.exports=function(t){return i((function(){var e=""[t]('"');return e!==e.toLowerCase()||e.split('"').length>3}))}},353:function(t,e,n){"use strict";n(327)},354:function(t,e,n){var i=n(0),r=n(355);i({global:!0,forced:parseInt!=r},{parseInt:r})},355:function(t,e,n){var i=n(2),r=n(1),a=n(19),s=n(328).trim,o=n(325),u=i.parseInt,l=i.Symbol,c=l&&l.iterator,h=/^[+-]?0x/i,p=8!==u(o+"08")||22!==u(o+"0x16")||c&&!r((function(){u(Object(c))}));t.exports=p?function(t,e){var n=s(a(t));return u(n,e>>>0||(h.test(n)?16:10))}:u},356:function(t,e,n){var i=n(78).PROPER,r=n(1),a=n(325);t.exports=function(t){return r((function(){return!!a[t]()||"β€‹Β…α Ž"!=="β€‹Β…α Ž"[t]()||i&&a[t].name!==t}))}},357:function(t,e,n){var i=n(4),r=n(5),a=n(79);t.exports=function(t,e,n){var s,o;return a&&i(s=e.constructor)&&s!==n&&r(o=s.prototype)&&o!==n.prototype&&a(t,o),t}},358:function(t,e,n){"use strict";var i,r=n(0),a=n(28).f,s=n(77),o=n(19),u=n(110),l=n(26),c=n(111),h=n(20),p="".endsWith,f=Math.min,d=c("endsWith");r({target:"String",proto:!0,forced:!!(h||d||(i=a(String.prototype,"endsWith"),!i||i.writable))&&!d},{endsWith:function(t){var e=o(l(this));u(t);var n=arguments.length>1?arguments[1]:void 0,i=e.length,r=void 0===n?i:f(s(n),i),a=o(t);return p?p.call(e,a,r):e.slice(r-a.length,r)===a}})},359:function(t,e,n){"use strict";n(332)},360:function(t,e,n){"use strict";n(333)},361:function(t,e,n){"use strict";n(334)},362:function(t,e,n){"use strict";n(335)},363:function(t,e,n){"use strict";n(336)},364:function(t,e,n){"use strict";n(337)},365:function(t,e,n){"use strict";n(339)},366:function(t,e,n){var i=n(33),r=n(15),a=n(29);t.exports=function(t){return"string"==typeof t||!r(t)&&a(t)&&"[object String]"==i(t)}},367:function(t,e,n){"use strict";n(340)},368:function(t,e,n){"use strict";n(341)},369:function(t,e,n){"use strict";n(342)},370:function(t,e,n){"use strict";var i=n(0),r=n(32).find,a=n(107),s=!0;"find"in[]&&Array(1).find((function(){s=!1})),i({target:"Array",proto:!0,forced:s},{find:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0)}}),a("find")},371:function(t,e,n){"use strict";n(343)},372:function(t,e,n){"use strict";n(344)},376:function(t,e,n){"use strict";n.r(e);n(350),n(102),n(103);var i=n(323),r={name:"NavLink",props:{item:{required:!0}},computed:{link:function(){return Object(i.b)(this.item.link)},exact:function(){var t=this;return this.$site.locales?Object.keys(this.$site.locales).some((function(e){return e===t.link})):"/"===this.link},isNonHttpURI:function(){return Object(i.g)(this.link)||Object(i.h)(this.link)},isBlankTarget:function(){return"_blank"===this.target},isInternal:function(){return!Object(i.f)(this.link)&&!this.isBlankTarget},target:function(){return this.isNonHttpURI?null:this.item.target?this.item.target:Object(i.f)(this.link)?"_blank":""},rel:function(){return this.isNonHttpURI||!1===this.item.rel?null:this.item.rel?this.item.rel:this.isBlankTarget?"noopener noreferrer":null}},methods:{focusoutAction:function(){this.$emit("focusout")}}},a=n(46),s=Object(a.a)(r,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.isInternal?n("RouterLink",{staticClass:"nav-link",attrs:{to:t.link,exact:t.exact},nativeOn:{focusout:function(e){return t.focusoutAction.apply(null,arguments)}}},[t._v("\n "+t._s(t.item.text)+"\n")]):n("a",{staticClass:"nav-link external",attrs:{href:t.link,target:t.target,rel:t.rel},on:{focusout:t.focusoutAction}},[t._v("\n "+t._s(t.item.text)+"\n "),t.isBlankTarget?n("OutboundLink"):t._e()],1)}),[],!1,null,null,null).exports,o={name:"Home",components:{NavLink:s},computed:{data:function(){return this.$page.frontmatter},actionLink:function(){return{link:this.data.actionLink,text:this.data.actionText}}}},u=(n(353),Object(a.a)(o,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("main",{staticClass:"home",attrs:{"aria-labelledby":null!==t.data.heroText?"main-title":null}},[n("header",{staticClass:"hero"},[t.data.heroImage?n("img",{attrs:{src:t.$withBase(t.data.heroImage),alt:t.data.heroAlt||"hero"}}):t._e(),t._v(" "),null!==t.data.heroText?n("h1",{attrs:{id:"main-title"}},[t._v("\n "+t._s(t.data.heroText||t.$title||"Hello")+"\n ")]):t._e(),t._v(" "),null!==t.data.tagline?n("p",{staticClass:"description"},[t._v("\n "+t._s(t.data.tagline||t.$description||"Welcome to your VuePress site")+"\n ")]):t._e(),t._v(" "),t.data.actionText&&t.data.actionLink?n("p",{staticClass:"action"},[n("NavLink",{staticClass:"action-button",attrs:{item:t.actionLink}})],1):t._e()]),t._v(" "),t.data.features&&t.data.features.length?n("div",{staticClass:"features"},t._l(t.data.features,(function(e,i){return n("div",{key:i,staticClass:"feature"},[n("h2",[t._v(t._s(e.title))]),t._v(" "),n("p",[t._v(t._s(e.details))])])})),0):t._e(),t._v(" "),n("Content",{staticClass:"theme-default-content custom"}),t._v(" "),t.data.footer?n("div",{staticClass:"footer"},[t._v("\n "+t._s(t.data.footer)+"\n ")]):t._e()],1)}),[],!1,null,null,null).exports),l=(n(354),n(329),n(175),n(106),n(31),n(47),n(324),n(186),n(187),n(182),n(76),n(330),n(331),n(75),n(326),n(358),n(189)),c=n.n(l),h=function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,i=c()(e,"title","");return c()(e,"frontmatter.tags")&&(i+=" ".concat(e.frontmatter.tags.join(" "))),n&&(i+=" ".concat(n)),p(t,i)},p=function(t,e){var n=function(t){return t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&")},i=new RegExp("[^\0-]"),r=t.split(/\s+/g).map((function(t){return t.trim()})).filter((function(t){return!!t}));if(i.test(t))return r.some((function(t){return e.toLowerCase().indexOf(t)>-1}));var a=t.endsWith(" ");return new RegExp(r.map((function(t,e){return r.length!==e+1||a?"(?=.*\\b".concat(n(t),"\\b)"):"(?=.*\\b".concat(n(t),")")})).join("")+".+","gi").test(e)},f={name:"SearchBox",data:function(){return{query:"",focused:!1,focusIndex:0,placeholder:void 0}},computed:{showSuggestions:function(){return this.focused&&this.suggestions&&this.suggestions.length},suggestions:function(){var t=this.query.trim().toLowerCase();if(t){for(var e=this.$site.pages,n=this.$site.themeConfig.searchMaxSuggestions||5,i=this.$localePath,r=[],a=0;a=n);a++){var s=e[a];if(this.getPageLocalePath(s)===i&&this.isSearchable(s))if(h(t,s))r.push(s);else if(s.headers)for(var o=0;o=n);o++){var u=s.headers[o];u.title&&h(t,s,u.title)&&r.push(Object.assign({},s,{path:s.path+"#"+u.slug,header:u}))}}return r}},alignRight:function(){return(this.$site.themeConfig.nav||[]).length+(this.$site.repo?1:0)<=2}},mounted:function(){this.placeholder=this.$site.themeConfig.searchPlaceholder||"",document.addEventListener("keydown",this.onHotkey)},beforeDestroy:function(){document.removeEventListener("keydown",this.onHotkey)},methods:{getPageLocalePath:function(t){for(var e in this.$site.locales||{})if("/"!==e&&0===t.path.indexOf(e))return e;return"/"},isSearchable:function(t){var e=null;return null===e||(e=Array.isArray(e)?e:new Array(e)).filter((function(e){return t.path.match(e)})).length>0},onHotkey:function(t){t.srcElement===document.body&&["s","/"].includes(t.key)&&(this.$refs.input.focus(),t.preventDefault())},onUp:function(){this.showSuggestions&&(this.focusIndex>0?this.focusIndex--:this.focusIndex=this.suggestions.length-1)},onDown:function(){this.showSuggestions&&(this.focusIndex "+t._s(e.header.title))]):t._e()])])})),0):t._e()])}),[],!1,null,null,null).exports),g=(n(360),Object(a.a)({},(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"sidebar-button",on:{click:function(e){return t.$emit("toggle-sidebar")}}},[n("svg",{staticClass:"icon",attrs:{xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",role:"img",viewBox:"0 0 448 512"}},[n("path",{attrs:{fill:"currentColor",d:"M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"}})])])}),[],!1,null,null,null).exports),v=n(44),m=(n(188),n(349)),b=n(190),k=n.n(b),_={name:"DropdownLink",components:{NavLink:s,DropdownTransition:m.a},props:{item:{required:!0}},data:function(){return{open:!1}},computed:{dropdownAriaLabel:function(){return this.item.ariaLabel||this.item.text}},watch:{$route:function(){this.open=!1}},methods:{setOpen:function(t){this.open=t},isLastItemOfArray:function(t,e){return k()(e)===t},handleDropdown:function(){0===event.detail&&this.setOpen(!this.open)}}},x=(n(362),{name:"NavLinks",components:{NavLink:s,DropdownLink:Object(a.a)(_,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"dropdown-wrapper",class:{open:t.open}},[n("button",{staticClass:"dropdown-title",attrs:{type:"button","aria-label":t.dropdownAriaLabel},on:{click:t.handleDropdown}},[n("span",{staticClass:"title"},[t._v(t._s(t.item.text))]),t._v(" "),n("span",{staticClass:"arrow down"})]),t._v(" "),n("button",{staticClass:"mobile-dropdown-title",attrs:{type:"button","aria-label":t.dropdownAriaLabel},on:{click:function(e){return t.setOpen(!t.open)}}},[n("span",{staticClass:"title"},[t._v(t._s(t.item.text))]),t._v(" "),n("span",{staticClass:"arrow",class:t.open?"down":"right"})]),t._v(" "),n("DropdownTransition",[n("ul",{directives:[{name:"show",rawName:"v-show",value:t.open,expression:"open"}],staticClass:"nav-dropdown"},t._l(t.item.items,(function(e,i){return n("li",{key:e.link||i,staticClass:"dropdown-item"},["links"===e.type?n("h4",[t._v("\n "+t._s(e.text)+"\n ")]):t._e(),t._v(" "),"links"===e.type?n("ul",{staticClass:"dropdown-subitem-wrapper"},t._l(e.items,(function(i){return n("li",{key:i.link,staticClass:"dropdown-subitem"},[n("NavLink",{attrs:{item:i},on:{focusout:function(n){t.isLastItemOfArray(i,e.items)&&t.isLastItemOfArray(e,t.item.items)&&t.setOpen(!1)}}})],1)})),0):n("NavLink",{attrs:{item:e},on:{focusout:function(n){t.isLastItemOfArray(e,t.item.items)&&t.setOpen(!1)}}})],1)})),0)])],1)}),[],!1,null,null,null).exports},computed:{userNav:function(){return this.$themeLocaleConfig.nav||this.$site.themeConfig.nav||[]},nav:function(){var t=this,e=this.$site.locales;if(e&&Object.keys(e).length>1){var n=this.$page.path,i=this.$router.options.routes,r=this.$site.themeConfig.locales||{},a={text:this.$themeLocaleConfig.selectText||"Languages",ariaLabel:this.$themeLocaleConfig.ariaLabel||"Select language",items:Object.keys(e).map((function(a){var s,o=e[a],u=r[a]&&r[a].label||o.lang;return o.lang===t.$lang?s=n:(s=n.replace(t.$localeConfig.path,a),i.some((function(t){return t.path===s}))||(s=a)),{text:u,link:s}}))};return[].concat(Object(v.a)(this.userNav),[a])}return this.userNav},userLinks:function(){return(this.nav||[]).map((function(t){return Object.assign(Object(i.j)(t),{items:(t.items||[]).map(i.j)})}))},repoLink:function(){var t=this.$site.themeConfig.repo;return t?/^https?:/.test(t)?t:"https://github.com/".concat(t):null},repoLabel:function(){if(this.repoLink){if(this.$site.themeConfig.repoLabel)return this.$site.themeConfig.repoLabel;for(var t=this.repoLink.match(/^https?:\/\/[^/]+/)[0],e=["GitHub","GitLab","Bitbucket"],n=0;nMath.abs(n)&&Math.abs(e)>40&&(e>0&&this.touchStart.x<=80?this.toggleSidebar(!0):this.toggleSidebar(!1))}}}),G=Object(a.a)(W,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"theme-container",class:t.pageClasses,on:{touchstart:t.onTouchStart,touchend:t.onTouchEnd}},[t.shouldShowNavbar?n("Navbar",{on:{"toggle-sidebar":t.toggleSidebar}}):t._e(),t._v(" "),n("div",{staticClass:"sidebar-mask",on:{click:function(e){return t.toggleSidebar(!1)}}}),t._v(" "),n("Sidebar",{attrs:{items:t.sidebarItems},on:{"toggle-sidebar":t.toggleSidebar},scopedSlots:t._u([{key:"top",fn:function(){return[t._t("sidebar-top")]},proxy:!0},{key:"bottom",fn:function(){return[t._t("sidebar-bottom")]},proxy:!0}],null,!0)}),t._v(" "),t.$page.frontmatter.home?n("Home"):n("Page",{attrs:{"sidebar-items":t.sidebarItems},scopedSlots:t._u([{key:"top",fn:function(){return[t._t("page-top")]},proxy:!0},{key:"bottom",fn:function(){return[t._t("page-bottom")]},proxy:!0}],null,!0)})],1)}),[],!1,null,null,null);e.default=G.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/20.daa52ffd.js b/docs/assets/js/20.c7598b24.js similarity index 95% rename from docs/assets/js/20.daa52ffd.js rename to docs/assets/js/20.c7598b24.js index c4710004e9..1706a8b5bd 100644 --- a/docs/assets/js/20.daa52ffd.js +++ b/docs/assets/js/20.c7598b24.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[20],{393:function(a,t,s){"use strict";s.r(t);var e=s(46),n=Object(e.a)({},(function(){var a=this,t=a.$createElement,s=a._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[s("h1",{attrs:{id:"validation"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#validation"}},[a._v("#")]),a._v(" Validation")]),a._v(" "),s("p",[a._v("Caliban provides a little macro called "),s("code",[a._v("gqldoc")]),a._v(" that can check at "),s("strong",[a._v("compile-time")]),a._v(" that a GraphQL query (a "),s("em",[a._v("document")]),a._v(" to be exact) has valid syntax.")]),a._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"}},[a._v("import")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[a._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")])]),a._v("Macros"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),a._v("gqldoc\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("val")]),a._v(" query "),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v(" gqldoc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),s("span",{pre:!0,attrs:{class:"token triple-quoted-string string"}},[a._v('"""\n query test {\n amos: character(name: "Amos Burton") {\n name\n }\n }"""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v("\n")])])]),s("p",[a._v("At "),s("strong",[a._v("runtime")]),a._v(", it is possible to validate a query against your schema by calling the method "),s("code",[a._v("check")]),a._v(" on your API.")]),a._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"}},[a._v("def")]),a._v(" check"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("query"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[a._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" IO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("[")]),a._v("CalibanError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[a._v("Unit")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("]")]),a._v("\n")])])]),s("p",[a._v("It is also possible to skip validation when executing a query by passing "),s("code",[a._v("skipValidation = true")]),a._v(" when calling "),s("code",[a._v("execute")]),a._v(" (also available in the adapters). This will slightly improve performance.")])])}),[],!1,null,null,null);t.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[20],{405:function(a,t,s){"use strict";s.r(t);var e=s(54),n=Object(e.a)({},(function(){var a=this,t=a.$createElement,s=a._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[s("h1",{attrs:{id:"validation"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#validation"}},[a._v("#")]),a._v(" Validation")]),a._v(" "),s("p",[a._v("Caliban provides a little macro called "),s("code",[a._v("gqldoc")]),a._v(" that can check at "),s("strong",[a._v("compile-time")]),a._v(" that a GraphQL query (a "),s("em",[a._v("document")]),a._v(" to be exact) has valid syntax.")]),a._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"}},[a._v("import")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[a._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")])]),a._v("Macros"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),a._v("gqldoc\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("val")]),a._v(" query "),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v("=")]),a._v(" gqldoc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),s("span",{pre:!0,attrs:{class:"token triple-quoted-string string"}},[a._v('"""\n query test {\n amos: character(name: "Amos Burton") {\n name\n }\n }"""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v("\n")])])]),s("p",[a._v("At "),s("strong",[a._v("runtime")]),a._v(", it is possible to validate a query against your schema by calling the method "),s("code",[a._v("check")]),a._v(" on your API.")]),a._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"}},[a._v("def")]),a._v(" check"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("query"),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[a._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" IO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("[")]),a._v("CalibanError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[a._v("Unit")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("]")]),a._v("\n")])])]),s("p",[a._v("It is also possible to skip validation when executing a query by passing "),s("code",[a._v("skipValidation = true")]),a._v(" when calling "),s("code",[a._v("execute")]),a._v(" (also available in the adapters). This will slightly improve performance.")])])}),[],!1,null,null,null);t.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/21.6563d4da.js b/docs/assets/js/21.2cc8bcb9.js similarity index 99% rename from docs/assets/js/21.6563d4da.js rename to docs/assets/js/21.2cc8bcb9.js index aa3fd7d11f..514b7a8ca6 100644 --- a/docs/assets/js/21.6563d4da.js +++ b/docs/assets/js/21.2cc8bcb9.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[21],{394:function(t,a,e){"use strict";e.r(a);var s=e(46),n=Object(s.a)({},(function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"faq"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#faq"}},[t._v("#")]),t._v(" FAQ")]),t._v(" "),e("h3",{attrs:{id:"i-don-t-know-where-to-start-πŸ˜₯"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#i-don-t-know-where-to-start-πŸ˜₯"}},[t._v("#")]),t._v(" I don't know where to start πŸ˜₯")]),t._v(" "),e("p",[t._v("No worries! Head to the "),e("a",{attrs:{href:"https://ghostdogpr.github.io/caliban/resources/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Resources"),e("OutboundLink")],1),t._v(" page to find a few introductory videos and blog posts. Once you're ready for more details, check the "),e("a",{attrs:{href:"https://ghostdogpr.github.io/caliban/docs/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Documentation"),e("OutboundLink")],1),t._v(". If you prefer looking at some code first, check "),e("a",{attrs:{href:"https://ghostdogpr.github.io/caliban/docs/examples.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("this list of examples"),e("OutboundLink")],1),t._v(".")]),t._v(" "),e("p",[t._v("If you're still lost, just come to the "),e("a",{attrs:{href:"https://discord.gg/EYpumuv",target:"_blank",rel:"noopener noreferrer"}},[t._v("Discord channel"),e("OutboundLink")],1),t._v("!")]),t._v(" "),e("h3",{attrs:{id:"i-m-getting-a-compilation-error-saying-a-schema-is-missing-but-i-don-t-know-which-one"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#i-m-getting-a-compilation-error-saying-a-schema-is-missing-but-i-don-t-know-which-one"}},[t._v("#")]),t._v(" I'm getting a compilation error saying a "),e("code",[t._v("Schema")]),t._v(" is missing, but I don't know which one.")]),t._v(" "),e("p",[t._v("Call directly "),e("code",[t._v("Schema.gen[YourType]")]),t._v(" or just "),e("code",[t._v("gen[YourType]")]),t._v(" if you extend "),e("code",[t._v("GenericSchema")]),t._v(". The error should be more detailed.")]),t._v(" "),e("h3",{attrs:{id:"i-want-to-use-caliban-but-i-use-cats-effect-monix-instead-of-zio"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#i-want-to-use-caliban-but-i-use-cats-effect-monix-instead-of-zio"}},[t._v("#")]),t._v(" I want to use Caliban, but I use Cats Effect / Monix instead of ZIO.")]),t._v(" "),e("p",[t._v('That\'s not a problem! Caliban has interop modules that "hide" the ZIO details and expose Cats Effect or Monix types instead. Check the '),e("a",{attrs:{href:"https://ghostdogpr.github.io/caliban/docs/interop.html#cats-effect",target:"_blank",rel:"noopener noreferrer"}},[t._v("interop docs"),e("OutboundLink")],1),t._v(" for more details.")]),t._v(" "),e("h3",{attrs:{id:"my-query-fails-with-an-effect-failure-error-how-can-i-get-more-details"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#my-query-fails-with-an-effect-failure-error-how-can-i-get-more-details"}},[t._v("#")]),t._v(' My query fails with an "Effect failure" error. How can I get more details?')]),t._v(" "),e("p",[t._v("When an error happens in one of the resolvers, Caliban doesn't expose the inner exception to the client by default (this might be unsafe to do so), but you can easily work around this by several ways:")]),t._v(" "),e("ol",[e("li",[t._v("If you fail with a "),e("code",[t._v("CalibanError.ExecutionError")]),t._v(", it won't be wrapped by Caliban so the original message will be displayed")]),t._v(" "),e("li",[t._v("Using the wrapper "),e("code",[t._v("@@ printErrors")]),t._v(" will print the full error to the console")]),t._v(" "),e("li",[t._v("Using "),e("code",[t._v("mapError")]),t._v(" on your interpreter lets you unwrap the "),e("code",[t._v("CalibanError")]),t._v(" and return your inner exception instead")])]),t._v(" "),e("h3",{attrs:{id:"i-have-more-than-22-fields-in-my-query-i-can-t-create-a-case-class-for-it"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#i-have-more-than-22-fields-in-my-query-i-can-t-create-a-case-class-for-it"}},[t._v("#")]),t._v(" I have more than 22 fields in my Query, I can't create a case class for it.")]),t._v(" "),e("p",[t._v("Instead of one huge case class with all your fields, you can create smaller case classes and combine "),e("code",[t._v("GraphQL")]),t._v(" objects using "),e("code",[t._v("|+|")]),t._v(".")]),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 keyword"}},[t._v("val")]),t._v(" api1 "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api2 "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" api1 "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" api2\n")])])]),e("h3",{attrs:{id:"how-to-deal-with-authentication-authorization"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#how-to-deal-with-authentication-authorization"}},[t._v("#")]),t._v(" How to deal with authentication/authorization?")]),t._v(" "),e("p",[t._v("This is typically handled with the help of ZIO environment. You can make your field require an "),e("code",[t._v("Auth")]),t._v(" service by returning a "),e("code",[t._v("ZIO[Auth, E, A]")]),t._v(". Then, in your resolver, access the "),e("code",[t._v("Auth")]),t._v(" service to check you have the appropriate permissions. You can inject the authentication information using a middleware in your HTTP server library. Check "),e("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/blob/master/examples/src/main/scala/example/http4s/AuthExampleApp.scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),e("OutboundLink")],1),t._v(" for a full example using http4s.")]),t._v(" "),e("h3",{attrs:{id:"i-have-2-case-classes-with-the-same-name-different-packages-how-to-avoid-conflicts"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#i-have-2-case-classes-with-the-same-name-different-packages-how-to-avoid-conflicts"}},[t._v("#")]),t._v(" I have 2 case classes with the same name (different packages). How to avoid conflicts?")]),t._v(" "),e("p",[t._v("You can use the annotation "),e("code",[t._v("@GQLName")]),t._v(" to give another name to any type or field.")]),t._v(" "),e("h3",{attrs:{id:"the-auto-generated-schema-shows-a-field-is-nullable-but-i-want-it-non-nullable-instead"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#the-auto-generated-schema-shows-a-field-is-nullable-but-i-want-it-non-nullable-instead"}},[t._v("#")]),t._v(" The auto-generated schema shows a field is nullable, but I want it non-nullable instead.")]),t._v(" "),e("p",[t._v("A GraphQL field is marked as nullable if the Scala field returns an "),e("code",[t._v("Option")]),t._v(" or an effect that can fail. Change your effect to return "),e("code",[t._v("UIO")]),t._v(" if you want the field to be non-nullable, and use "),e("code",[t._v("orDie")]),t._v(" if you want to fail the whole query in case of error instead of returning null.")]),t._v(" "),e("h3",{attrs:{id:"can-i-use-a-union-as-input"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#can-i-use-a-union-as-input"}},[t._v("#")]),t._v(" Can I use a union as input?")]),t._v(" "),e("p",[t._v("Unfortunately, it is not supported by the GraphQL spec. See "),e("a",{attrs:{href:"https://github.com/graphql/graphql-spec/issues/488",target:"_blank",rel:"noopener noreferrer"}},[t._v("https://github.com/graphql/graphql-spec/issues/488"),e("OutboundLink")],1),t._v(" for discussions. An alternative can be to define your own custom scalar.")]),t._v(" "),e("h3",{attrs:{id:"how-to-deal-with-recursive-types"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#how-to-deal-with-recursive-types"}},[t._v("#")]),t._v(" How to deal with recursive types?")]),t._v(" "),e("p",[t._v("Recursive types can be a little tricky. This is not a silver bullet but usually the trick is to add an "),e("code",[t._v("implicit lazy val")]),t._v(" instance of "),e("code",[t._v("Schema")]),t._v(" for the type that is recursive. See "),e("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/blob/master/examples/src/main/scala/example/optimizations/NaiveTest.scala#L82",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),e("OutboundLink")],1),t._v(" for an example.")]),t._v(" "),e("h3",{attrs:{id:"i-m-getting-a-method-too-large-compiler-error"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#i-m-getting-a-method-too-large-compiler-error"}},[t._v("#")]),t._v(' I\'m getting a "Method too large" compiler error.')]),t._v(" "),e("p",[t._v("When you create a GraphQL API, Caliban (using a macro powered by "),e("a",{attrs:{href:"https://github.com/propensive/magnolia",target:"_blank",rel:"noopener noreferrer"}},[t._v("Magnolia"),e("OutboundLink")],1),t._v(") generates a schema for every type, everywhere it's used. If you use a lot of types, the generated code might be too large. The workaround is to define schemas for your intermediate types:")]),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 keyword"}},[t._v("implicit")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schemaMyType"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyType"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])]),e("p",[t._v("That way, the schema for this type will be extracted to a single method and defined only once. Do it in priority with types that are re-used in a lot of places: this will reduce the amount of generated code and will speed up compilation time.")]),t._v(" "),e("h3",{attrs:{id:"how-can-i-define-a-schema-for-a-java-enum"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#how-can-i-define-a-schema-for-a-java-enum"}},[t._v("#")]),t._v(" How can I define a "),e("code",[t._v("Schema")]),t._v(" for a Java enum?")]),t._v(" "),e("p",[t._v("Here's an example for Java "),e("code",[t._v("DayOfWeek")]),t._v(":")]),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 keyword"}},[t._v("implicit")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" dayOfWeekSchema "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" Schema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" DayOfWeek"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" toType"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("isInput"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Boolean")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" __Type "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Types"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("makeEnum"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Some"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"DayOfWeek"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n None"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n DayOfWeek"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("values"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toList"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" __EnumValue"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n None\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" resolve"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" DayOfWeek"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Step"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" PureStep"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("StringValue"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("h3",{attrs:{id:"i-don-t-want-to-use-throwable-as-my-error-type"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#i-don-t-want-to-use-throwable-as-my-error-type"}},[t._v("#")]),t._v(" I don't want to use "),e("code",[t._v("Throwable")]),t._v(" as my error type")]),t._v(" "),e("p",[t._v("Caliban provides "),e("code",[t._v("Schema")]),t._v(" instances for "),e("code",[t._v("ZIO")]),t._v(", "),e("code",[t._v("ZQuery")]),t._v(" and "),e("code",[t._v("ZStream")]),t._v(" but with the condition that the error type is a "),e("code",[t._v("Throwable")]),t._v(".\nThat is because the error is eventually wrapped inside Caliban "),e("code",[t._v("ExecutionError")]),t._v(" and we need to know what it is.\nHowever, you can easily define a custom "),e("code",[t._v("Schema")]),t._v(" without this constraint, as long as you provide a function from your error type to "),e("code",[t._v("ExecutionError")]),t._v(".")]),t._v(" "),e("p",[t._v("For example, if your error type is "),e("code",[t._v("Int")]),t._v(", you can use "),e("code",[t._v("Schema.customErrorEffectSchema")]),t._v(" as follows:")]),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 keyword"}},[t._v("implicit")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" customEffectSchema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("A"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" s"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IO"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Schema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("customErrorEffectSchema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("code"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ExecutionError"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Error code $code"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("With this implicit in scope, Caliban will know how to handle any "),e("code",[t._v("IO[Int, A]")]),t._v(" effects.\nCaliban will automatically fill the error path and the error location inside "),e("code",[t._v("ExecutionError")]),t._v(" if an error happens during the query execution.")])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[21],{406:function(t,a,e){"use strict";e.r(a);var s=e(54),n=Object(s.a)({},(function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"faq"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#faq"}},[t._v("#")]),t._v(" FAQ")]),t._v(" "),e("h3",{attrs:{id:"i-don-t-know-where-to-start-πŸ˜₯"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#i-don-t-know-where-to-start-πŸ˜₯"}},[t._v("#")]),t._v(" I don't know where to start πŸ˜₯")]),t._v(" "),e("p",[t._v("No worries! Head to the "),e("a",{attrs:{href:"https://ghostdogpr.github.io/caliban/resources/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Resources"),e("OutboundLink")],1),t._v(" page to find a few introductory videos and blog posts. Once you're ready for more details, check the "),e("a",{attrs:{href:"https://ghostdogpr.github.io/caliban/docs/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Documentation"),e("OutboundLink")],1),t._v(". If you prefer looking at some code first, check "),e("a",{attrs:{href:"https://ghostdogpr.github.io/caliban/docs/examples.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("this list of examples"),e("OutboundLink")],1),t._v(".")]),t._v(" "),e("p",[t._v("If you're still lost, just come to the "),e("a",{attrs:{href:"https://discord.gg/EYpumuv",target:"_blank",rel:"noopener noreferrer"}},[t._v("Discord channel"),e("OutboundLink")],1),t._v("!")]),t._v(" "),e("h3",{attrs:{id:"i-m-getting-a-compilation-error-saying-a-schema-is-missing-but-i-don-t-know-which-one"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#i-m-getting-a-compilation-error-saying-a-schema-is-missing-but-i-don-t-know-which-one"}},[t._v("#")]),t._v(" I'm getting a compilation error saying a "),e("code",[t._v("Schema")]),t._v(" is missing, but I don't know which one.")]),t._v(" "),e("p",[t._v("Call directly "),e("code",[t._v("Schema.gen[YourType]")]),t._v(" or just "),e("code",[t._v("gen[YourType]")]),t._v(" if you extend "),e("code",[t._v("GenericSchema")]),t._v(". The error should be more detailed.")]),t._v(" "),e("h3",{attrs:{id:"i-want-to-use-caliban-but-i-use-cats-effect-monix-instead-of-zio"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#i-want-to-use-caliban-but-i-use-cats-effect-monix-instead-of-zio"}},[t._v("#")]),t._v(" I want to use Caliban, but I use Cats Effect / Monix instead of ZIO.")]),t._v(" "),e("p",[t._v('That\'s not a problem! Caliban has interop modules that "hide" the ZIO details and expose Cats Effect or Monix types instead. Check the '),e("a",{attrs:{href:"https://ghostdogpr.github.io/caliban/docs/interop.html#cats-effect",target:"_blank",rel:"noopener noreferrer"}},[t._v("interop docs"),e("OutboundLink")],1),t._v(" for more details.")]),t._v(" "),e("h3",{attrs:{id:"my-query-fails-with-an-effect-failure-error-how-can-i-get-more-details"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#my-query-fails-with-an-effect-failure-error-how-can-i-get-more-details"}},[t._v("#")]),t._v(' My query fails with an "Effect failure" error. How can I get more details?')]),t._v(" "),e("p",[t._v("When an error happens in one of the resolvers, Caliban doesn't expose the inner exception to the client by default (this might be unsafe to do so), but you can easily work around this by several ways:")]),t._v(" "),e("ol",[e("li",[t._v("If you fail with a "),e("code",[t._v("CalibanError.ExecutionError")]),t._v(", it won't be wrapped by Caliban so the original message will be displayed")]),t._v(" "),e("li",[t._v("Using the wrapper "),e("code",[t._v("@@ printErrors")]),t._v(" will print the full error to the console")]),t._v(" "),e("li",[t._v("Using "),e("code",[t._v("mapError")]),t._v(" on your interpreter lets you unwrap the "),e("code",[t._v("CalibanError")]),t._v(" and return your inner exception instead")])]),t._v(" "),e("h3",{attrs:{id:"i-have-more-than-22-fields-in-my-query-i-can-t-create-a-case-class-for-it"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#i-have-more-than-22-fields-in-my-query-i-can-t-create-a-case-class-for-it"}},[t._v("#")]),t._v(" I have more than 22 fields in my Query, I can't create a case class for it.")]),t._v(" "),e("p",[t._v("Instead of one huge case class with all your fields, you can create smaller case classes and combine "),e("code",[t._v("GraphQL")]),t._v(" objects using "),e("code",[t._v("|+|")]),t._v(".")]),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 keyword"}},[t._v("val")]),t._v(" api1 "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api2 "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" api1 "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" api2\n")])])]),e("h3",{attrs:{id:"how-to-deal-with-authentication-authorization"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#how-to-deal-with-authentication-authorization"}},[t._v("#")]),t._v(" How to deal with authentication/authorization?")]),t._v(" "),e("p",[t._v("This is typically handled with the help of ZIO environment. You can make your field require an "),e("code",[t._v("Auth")]),t._v(" service by returning a "),e("code",[t._v("ZIO[Auth, E, A]")]),t._v(". Then, in your resolver, access the "),e("code",[t._v("Auth")]),t._v(" service to check you have the appropriate permissions. You can inject the authentication information using a middleware in your HTTP server library. Check "),e("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/blob/master/examples/src/main/scala/example/http4s/AuthExampleApp.scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),e("OutboundLink")],1),t._v(" for a full example using http4s.")]),t._v(" "),e("h3",{attrs:{id:"i-have-2-case-classes-with-the-same-name-different-packages-how-to-avoid-conflicts"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#i-have-2-case-classes-with-the-same-name-different-packages-how-to-avoid-conflicts"}},[t._v("#")]),t._v(" I have 2 case classes with the same name (different packages). How to avoid conflicts?")]),t._v(" "),e("p",[t._v("You can use the annotation "),e("code",[t._v("@GQLName")]),t._v(" to give another name to any type or field.")]),t._v(" "),e("h3",{attrs:{id:"the-auto-generated-schema-shows-a-field-is-nullable-but-i-want-it-non-nullable-instead"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#the-auto-generated-schema-shows-a-field-is-nullable-but-i-want-it-non-nullable-instead"}},[t._v("#")]),t._v(" The auto-generated schema shows a field is nullable, but I want it non-nullable instead.")]),t._v(" "),e("p",[t._v("A GraphQL field is marked as nullable if the Scala field returns an "),e("code",[t._v("Option")]),t._v(" or an effect that can fail. Change your effect to return "),e("code",[t._v("UIO")]),t._v(" if you want the field to be non-nullable, and use "),e("code",[t._v("orDie")]),t._v(" if you want to fail the whole query in case of error instead of returning null.")]),t._v(" "),e("h3",{attrs:{id:"can-i-use-a-union-as-input"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#can-i-use-a-union-as-input"}},[t._v("#")]),t._v(" Can I use a union as input?")]),t._v(" "),e("p",[t._v("Unfortunately, it is not supported by the GraphQL spec. See "),e("a",{attrs:{href:"https://github.com/graphql/graphql-spec/issues/488",target:"_blank",rel:"noopener noreferrer"}},[t._v("https://github.com/graphql/graphql-spec/issues/488"),e("OutboundLink")],1),t._v(" for discussions. An alternative can be to define your own custom scalar.")]),t._v(" "),e("h3",{attrs:{id:"how-to-deal-with-recursive-types"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#how-to-deal-with-recursive-types"}},[t._v("#")]),t._v(" How to deal with recursive types?")]),t._v(" "),e("p",[t._v("Recursive types can be a little tricky. This is not a silver bullet but usually the trick is to add an "),e("code",[t._v("implicit lazy val")]),t._v(" instance of "),e("code",[t._v("Schema")]),t._v(" for the type that is recursive. See "),e("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/blob/master/examples/src/main/scala/example/optimizations/NaiveTest.scala#L82",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),e("OutboundLink")],1),t._v(" for an example.")]),t._v(" "),e("h3",{attrs:{id:"i-m-getting-a-method-too-large-compiler-error"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#i-m-getting-a-method-too-large-compiler-error"}},[t._v("#")]),t._v(' I\'m getting a "Method too large" compiler error.')]),t._v(" "),e("p",[t._v("When you create a GraphQL API, Caliban (using a macro powered by "),e("a",{attrs:{href:"https://github.com/propensive/magnolia",target:"_blank",rel:"noopener noreferrer"}},[t._v("Magnolia"),e("OutboundLink")],1),t._v(") generates a schema for every type, everywhere it's used. If you use a lot of types, the generated code might be too large. The workaround is to define schemas for your intermediate types:")]),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 keyword"}},[t._v("implicit")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schemaMyType"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyType"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])]),e("p",[t._v("That way, the schema for this type will be extracted to a single method and defined only once. Do it in priority with types that are re-used in a lot of places: this will reduce the amount of generated code and will speed up compilation time.")]),t._v(" "),e("h3",{attrs:{id:"how-can-i-define-a-schema-for-a-java-enum"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#how-can-i-define-a-schema-for-a-java-enum"}},[t._v("#")]),t._v(" How can I define a "),e("code",[t._v("Schema")]),t._v(" for a Java enum?")]),t._v(" "),e("p",[t._v("Here's an example for Java "),e("code",[t._v("DayOfWeek")]),t._v(":")]),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 keyword"}},[t._v("implicit")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" dayOfWeekSchema "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" Schema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" DayOfWeek"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" toType"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("isInput"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Boolean")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" __Type "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Types"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("makeEnum"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Some"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"DayOfWeek"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n None"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n DayOfWeek"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("values"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toList"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" __EnumValue"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n None\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" resolve"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" DayOfWeek"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Step"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" PureStep"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("StringValue"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("h3",{attrs:{id:"i-don-t-want-to-use-throwable-as-my-error-type"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#i-don-t-want-to-use-throwable-as-my-error-type"}},[t._v("#")]),t._v(" I don't want to use "),e("code",[t._v("Throwable")]),t._v(" as my error type")]),t._v(" "),e("p",[t._v("Caliban provides "),e("code",[t._v("Schema")]),t._v(" instances for "),e("code",[t._v("ZIO")]),t._v(", "),e("code",[t._v("ZQuery")]),t._v(" and "),e("code",[t._v("ZStream")]),t._v(" but with the condition that the error type is a "),e("code",[t._v("Throwable")]),t._v(".\nThat is because the error is eventually wrapped inside Caliban "),e("code",[t._v("ExecutionError")]),t._v(" and we need to know what it is.\nHowever, you can easily define a custom "),e("code",[t._v("Schema")]),t._v(" without this constraint, as long as you provide a function from your error type to "),e("code",[t._v("ExecutionError")]),t._v(".")]),t._v(" "),e("p",[t._v("For example, if your error type is "),e("code",[t._v("Int")]),t._v(", you can use "),e("code",[t._v("Schema.customErrorEffectSchema")]),t._v(" as follows:")]),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 keyword"}},[t._v("implicit")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" customEffectSchema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("A"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" s"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IO"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Schema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("customErrorEffectSchema"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("code"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ExecutionError"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Error code $code"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("With this implicit in scope, Caliban will know how to handle any "),e("code",[t._v("IO[Int, A]")]),t._v(" effects.\nCaliban will automatically fill the error path and the error location inside "),e("code",[t._v("ExecutionError")]),t._v(" if an error happens during the query execution.")])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/22.724ace4d.js b/docs/assets/js/22.40e3cec2.js similarity index 97% rename from docs/assets/js/22.724ace4d.js rename to docs/assets/js/22.40e3cec2.js index 2e630245b6..7e48f19ba5 100644 --- a/docs/assets/js/22.724ace4d.js +++ b/docs/assets/js/22.40e3cec2.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[22],{395:function(a,e,t){"use strict";t.r(e);var r=t(46),n=Object(r.a)({},(function(){var a=this,e=a.$createElement,t=a._self._c||e;return t("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[t("h1",{attrs:{id:"resources"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#resources"}},[a._v("#")]),a._v(" Resources")]),a._v(" "),t("h2",{attrs:{id:"talks"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#talks"}},[a._v("#")]),a._v(" Talks")]),a._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://youtu.be/mzqsXklbmfM",target:"_blank",rel:"noopener noreferrer"}},[a._v("Zymposium episode on Caliban"),t("OutboundLink")],1),a._v(" with Pierre Ricadat, Kit Langton and Adam Fraser in June 2021")]),a._v(" "),t("li",[t("a",{attrs:{href:"https://www.youtube.com/watch?v=lgxUKsOH65k",target:"_blank",rel:"noopener noreferrer"}},[a._v("A Tour of Caliban"),t("OutboundLink")],1),a._v(" by Pierre Ricadat at "),t("a",{attrs:{href:"https://www.meetup.com/SF-Scala/",target:"_blank",rel:"noopener noreferrer"}},[a._v("SF Scala"),t("OutboundLink")],1),a._v(" in April 2020")]),a._v(" "),t("li",[t("a",{attrs:{href:"https://www.youtube.com/watch?v=OC8PbviYUlQ",target:"_blank",rel:"noopener noreferrer"}},[a._v("Caliban: Designing a Functional GraphQL Library"),t("OutboundLink")],1),a._v(" by Pierre Ricadat at "),t("a",{attrs:{href:"https://www.functionalscala.com/",target:"_blank",rel:"noopener noreferrer"}},[a._v("Functional Scala"),t("OutboundLink")],1),a._v(" in December 2019 (slides available "),t("a",{attrs:{href:"https://www.slideshare.net/PierreRicadat/designing-a-functional-graphql-library-204680947",target:"_blank",rel:"noopener noreferrer"}},[a._v("here"),t("OutboundLink")],1),a._v(")")])]),a._v(" "),t("h2",{attrs:{id:"blog-articles"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#blog-articles"}},[a._v("#")]),a._v(" Blog Articles")]),a._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://medium.com/@ghostdogpr/caliban-client-a-type-safe-graphql-client-for-scala-and-scala-js-718aa42c5ef7",target:"_blank",rel:"noopener noreferrer"}},[a._v("Caliban Client: a type-safe GraphQL Client for Scala and Scala.js"),t("OutboundLink")],1),a._v(" by Pierre Ricadat (February 2020)")]),a._v(" "),t("li",[t("strong",[t("em",[a._v("GraphQL in Scala with Caliban")])]),a._v(" by Pierre Ricadat (February 2020)\n"),t("ul",[t("li",[t("a",{attrs:{href:"https://medium.com/@ghostdogpr/graphql-in-scala-with-caliban-part-1-8ceb6099c3c2",target:"_blank",rel:"noopener noreferrer"}},[a._v("Part 1: Turn a simple API into GraphQL"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://medium.com/@ghostdogpr/graphql-in-scala-with-caliban-part-2-c7762110c0f9",target:"_blank",rel:"noopener noreferrer"}},[a._v("Part 2: Query optimization"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://medium.com/@ghostdogpr/graphql-in-scala-with-caliban-part-3-8962a02d5d64",target:"_blank",rel:"noopener noreferrer"}},[a._v("Part 3: Customization using wrappers"),t("OutboundLink")],1)])])]),a._v(" "),t("li",[t("a",{attrs:{href:"http://fokot.github.io/post/caliban-auth.html",target:"_blank",rel:"noopener noreferrer"}},[a._v("Authentication in Caliban"),t("OutboundLink")],1),a._v(" by FrantiΕ‘ek Kocun (December 2019)")])]),a._v(" "),t("h2",{attrs:{id:"related-projects"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#related-projects"}},[a._v("#")]),a._v(" Related Projects")]),a._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://zio.github.io/caliban-deriving/",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-deriving"),t("OutboundLink")],1),a._v(": an alternative schema derivation implementation that supports additional use cases such as deriving fields from class methods (can be used side by side with caliban regular derivation, on the types you want).")]),a._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/niqdev/caliban-extras",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-extras"),t("OutboundLink")],1),a._v(": a project bringing some goodies to caliban, including "),t("a",{attrs:{href:"https://github.com/niqdev/caliban-extras#caliban-refined",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-refined"),t("OutboundLink")],1),a._v(", a module to automatically derive schemas for "),t("a",{attrs:{href:"https://github.com/fthomas/refined",target:"_blank",rel:"noopener noreferrer"}},[a._v("refined"),t("OutboundLink")],1),a._v(" types.")]),a._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ScalaConsultants/zio-akka-quickstart.g8",target:"_blank",rel:"noopener noreferrer"}},[a._v("zio-akka-quickstart"),t("OutboundLink")],1),a._v(": a Giter8 template for a basic Scala application built using ZIO, Akka HTTP, Slick and Caliban!")]),a._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/fokot/caliban-talk",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-talk"),t("OutboundLink")],1),a._v(": example project using ZIO, http4s, doobie/quill, caliban-client, testcontainers and Caliban")]),a._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/swachter/caliban-test",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-test"),t("OutboundLink")],1),a._v(": example project using ZIO, Caliban, and jOOQ for accessing a relation database")])])])}),[],!1,null,null,null);e.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[22],{407:function(a,e,t){"use strict";t.r(e);var r=t(54),n=Object(r.a)({},(function(){var a=this,e=a.$createElement,t=a._self._c||e;return t("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[t("h1",{attrs:{id:"resources"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#resources"}},[a._v("#")]),a._v(" Resources")]),a._v(" "),t("h2",{attrs:{id:"talks"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#talks"}},[a._v("#")]),a._v(" Talks")]),a._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://youtu.be/mzqsXklbmfM",target:"_blank",rel:"noopener noreferrer"}},[a._v("Zymposium episode on Caliban"),t("OutboundLink")],1),a._v(" with Pierre Ricadat, Kit Langton and Adam Fraser in June 2021")]),a._v(" "),t("li",[t("a",{attrs:{href:"https://www.youtube.com/watch?v=lgxUKsOH65k",target:"_blank",rel:"noopener noreferrer"}},[a._v("A Tour of Caliban"),t("OutboundLink")],1),a._v(" by Pierre Ricadat at "),t("a",{attrs:{href:"https://www.meetup.com/SF-Scala/",target:"_blank",rel:"noopener noreferrer"}},[a._v("SF Scala"),t("OutboundLink")],1),a._v(" in April 2020")]),a._v(" "),t("li",[t("a",{attrs:{href:"https://www.youtube.com/watch?v=OC8PbviYUlQ",target:"_blank",rel:"noopener noreferrer"}},[a._v("Caliban: Designing a Functional GraphQL Library"),t("OutboundLink")],1),a._v(" by Pierre Ricadat at "),t("a",{attrs:{href:"https://www.functionalscala.com/",target:"_blank",rel:"noopener noreferrer"}},[a._v("Functional Scala"),t("OutboundLink")],1),a._v(" in December 2019 (slides available "),t("a",{attrs:{href:"https://www.slideshare.net/PierreRicadat/designing-a-functional-graphql-library-204680947",target:"_blank",rel:"noopener noreferrer"}},[a._v("here"),t("OutboundLink")],1),a._v(")")])]),a._v(" "),t("h2",{attrs:{id:"blog-articles"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#blog-articles"}},[a._v("#")]),a._v(" Blog Articles")]),a._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://medium.com/@ghostdogpr/caliban-client-a-type-safe-graphql-client-for-scala-and-scala-js-718aa42c5ef7",target:"_blank",rel:"noopener noreferrer"}},[a._v("Caliban Client: a type-safe GraphQL Client for Scala and Scala.js"),t("OutboundLink")],1),a._v(" by Pierre Ricadat (February 2020)")]),a._v(" "),t("li",[t("strong",[t("em",[a._v("GraphQL in Scala with Caliban")])]),a._v(" by Pierre Ricadat (February 2020)\n"),t("ul",[t("li",[t("a",{attrs:{href:"https://medium.com/@ghostdogpr/graphql-in-scala-with-caliban-part-1-8ceb6099c3c2",target:"_blank",rel:"noopener noreferrer"}},[a._v("Part 1: Turn a simple API into GraphQL"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://medium.com/@ghostdogpr/graphql-in-scala-with-caliban-part-2-c7762110c0f9",target:"_blank",rel:"noopener noreferrer"}},[a._v("Part 2: Query optimization"),t("OutboundLink")],1)]),a._v(" "),t("li",[t("a",{attrs:{href:"https://medium.com/@ghostdogpr/graphql-in-scala-with-caliban-part-3-8962a02d5d64",target:"_blank",rel:"noopener noreferrer"}},[a._v("Part 3: Customization using wrappers"),t("OutboundLink")],1)])])]),a._v(" "),t("li",[t("a",{attrs:{href:"http://fokot.github.io/post/caliban-auth.html",target:"_blank",rel:"noopener noreferrer"}},[a._v("Authentication in Caliban"),t("OutboundLink")],1),a._v(" by FrantiΕ‘ek Kocun (December 2019)")])]),a._v(" "),t("h2",{attrs:{id:"related-projects"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#related-projects"}},[a._v("#")]),a._v(" Related Projects")]),a._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://zio.github.io/caliban-deriving/",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-deriving"),t("OutboundLink")],1),a._v(": an alternative schema derivation implementation that supports additional use cases such as deriving fields from class methods (can be used side by side with caliban regular derivation, on the types you want).")]),a._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/niqdev/caliban-extras",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-extras"),t("OutboundLink")],1),a._v(": a project bringing some goodies to caliban, including "),t("a",{attrs:{href:"https://github.com/niqdev/caliban-extras#caliban-refined",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-refined"),t("OutboundLink")],1),a._v(", a module to automatically derive schemas for "),t("a",{attrs:{href:"https://github.com/fthomas/refined",target:"_blank",rel:"noopener noreferrer"}},[a._v("refined"),t("OutboundLink")],1),a._v(" types.")]),a._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ScalaConsultants/zio-akka-quickstart.g8",target:"_blank",rel:"noopener noreferrer"}},[a._v("zio-akka-quickstart"),t("OutboundLink")],1),a._v(": a Giter8 template for a basic Scala application built using ZIO, Akka HTTP, Slick and Caliban!")]),a._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/fokot/caliban-talk",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-talk"),t("OutboundLink")],1),a._v(": example project using ZIO, http4s, doobie/quill, caliban-client, testcontainers and Caliban")]),a._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/swachter/caliban-test",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-test"),t("OutboundLink")],1),a._v(": example project using ZIO, Caliban, and jOOQ for accessing a relation database")])])])}),[],!1,null,null,null);e.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/3.cc5ee1dd.js b/docs/assets/js/3.831b4f47.js similarity index 62% rename from docs/assets/js/3.cc5ee1dd.js rename to docs/assets/js/3.831b4f47.js index 205660d275..1908a5223d 100644 --- a/docs/assets/js/3.cc5ee1dd.js +++ b/docs/assets/js/3.831b4f47.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[3],{345:function(t,e,n){},373:function(t,e,n){"use strict";n(345)},396:function(t,e,n){"use strict";n.r(e);var i={functional:!0,props:{type:{type:String,default:"tip"},text:String,vertical:{type:String,default:"top"}},render:function(t,e){var n=e.props,i=e.slots;return t("span",{class:["badge",n.type],style:{verticalAlign:n.vertical}},n.text||i().default)}},r=(n(373),n(46)),p=Object(r.a)(i,void 0,void 0,!1,null,"15b7b770",null);e.default=p.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[3],{357:function(t,e,n){},385:function(t,e,n){"use strict";n(357)},408:function(t,e,n){"use strict";n.r(e);var i={functional:!0,props:{type:{type:String,default:"tip"},text:String,vertical:{type:String,default:"top"}},render:function(t,e){var n=e.props,i=e.slots;return t("span",{class:["badge",n.type],style:{verticalAlign:n.vertical}},n.text||i().default)}},r=(n(385),n(54)),p=Object(r.a)(i,void 0,void 0,!1,null,"15b7b770",null);e.default=p.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/4.b5c5d85a.js b/docs/assets/js/4.9c0d3927.js similarity index 67% rename from docs/assets/js/4.b5c5d85a.js rename to docs/assets/js/4.9c0d3927.js index d6b1070c09..bca8f2bd7f 100644 --- a/docs/assets/js/4.b5c5d85a.js +++ b/docs/assets/js/4.9c0d3927.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[4],{346:function(t,e,a){},374:function(t,e,a){"use strict";a(346)},378:function(t,e,a){"use strict";a.r(e);var n={name:"CodeBlock",props:{title:{type:String,required:!0},active:{type:Boolean,default:!1}},mounted:function(){this.$parent&&this.$parent.loadTabs&&this.$parent.loadTabs()}},i=(a(374),a(46)),s=Object(i.a)(n,(function(){var t=this.$createElement;return(this._self._c||t)("div",{staticClass:"theme-code-block",class:{"theme-code-block__active":this.active}},[this._t("default")],2)}),[],!1,null,"759a7d02",null);e.default=s.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[4],{358:function(t,e,a){},386:function(t,e,a){"use strict";a(358)},390:function(t,e,a){"use strict";a.r(e);var n={name:"CodeBlock",props:{title:{type:String,required:!0},active:{type:Boolean,default:!1}},mounted:function(){this.$parent&&this.$parent.loadTabs&&this.$parent.loadTabs()}},i=(a(386),a(54)),s=Object(i.a)(n,(function(){var t=this.$createElement;return(this._self._c||t)("div",{staticClass:"theme-code-block",class:{"theme-code-block__active":this.active}},[this._t("default")],2)}),[],!1,null,"759a7d02",null);e.default=s.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/5.8fb2962b.js b/docs/assets/js/5.8fb2962b.js new file mode 100644 index 0000000000..3be06a051f --- /dev/null +++ b/docs/assets/js/5.8fb2962b.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[5],{359:function(e,t,a){},387:function(e,t,a){"use strict";a(359)},391:function(e,t,a){"use strict";a.r(t);a(81),a(34),a(6),a(111),a(112);var o={name:"CodeGroup",data:function(){return{codeTabs:[],activeCodeTabIndex:-1}},watch:{activeCodeTabIndex:function(e){this.activateCodeTab(e)}},mounted:function(){this.loadTabs()},methods:{changeCodeTab:function(e){this.activeCodeTabIndex=e},loadTabs:function(){var e=this;this.codeTabs=(this.$slots.default||[]).filter((function(e){return Boolean(e.componentOptions)})).map((function(t,a){return""===t.componentOptions.propsData.active&&(e.activeCodeTabIndex=a),{title:t.componentOptions.propsData.title,elm:t.elm}})),-1===this.activeCodeTabIndex&&this.codeTabs.length>0&&(this.activeCodeTabIndex=0),this.activateCodeTab(0)},activateCodeTab:function(e){this.codeTabs.forEach((function(e){e.elm&&e.elm.classList.remove("theme-code-block__active")})),this.codeTabs[e].elm&&this.codeTabs[e].elm.classList.add("theme-code-block__active")}}},n=(a(387),a(54)),c=Object(n.a)(o,(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("ClientOnly",[a("div",{staticClass:"theme-code-group"},[a("div",{staticClass:"theme-code-group__nav"},[a("ul",{staticClass:"theme-code-group__ul"},e._l(e.codeTabs,(function(t,o){return a("li",{key:t.title,staticClass:"theme-code-group__li"},[a("button",{staticClass:"theme-code-group__nav-tab",class:{"theme-code-group__nav-tab-active":o===e.activeCodeTabIndex},on:{click:function(t){return e.changeCodeTab(o)}}},[e._v("\n "+e._s(t.title)+"\n ")])])})),0)]),e._v(" "),e._t("default"),e._v(" "),e.codeTabs.length<1?a("pre",{staticClass:"pre-blank"},[e._v("// Make sure to add code blocks to your code group")]):e._e()],2)])}),[],!1,null,"deefee04",null);t.default=c.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/5.aedbb9bc.js b/docs/assets/js/5.aedbb9bc.js deleted file mode 100644 index b1320f86bd..0000000000 --- a/docs/assets/js/5.aedbb9bc.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[5],{347:function(e,t,a){},375:function(e,t,a){"use strict";a(347)},379:function(e,t,a){"use strict";a.r(t);a(75),a(31),a(104),a(105);var o={name:"CodeGroup",data:function(){return{codeTabs:[],activeCodeTabIndex:-1}},watch:{activeCodeTabIndex:function(e){this.activateCodeTab(e)}},mounted:function(){this.loadTabs()},methods:{changeCodeTab:function(e){this.activeCodeTabIndex=e},loadTabs:function(){var e=this;this.codeTabs=(this.$slots.default||[]).filter((function(e){return Boolean(e.componentOptions)})).map((function(t,a){return""===t.componentOptions.propsData.active&&(e.activeCodeTabIndex=a),{title:t.componentOptions.propsData.title,elm:t.elm}})),-1===this.activeCodeTabIndex&&this.codeTabs.length>0&&(this.activeCodeTabIndex=0),this.activateCodeTab(0)},activateCodeTab:function(e){this.codeTabs.forEach((function(e){e.elm&&e.elm.classList.remove("theme-code-block__active")})),this.codeTabs[e].elm&&this.codeTabs[e].elm.classList.add("theme-code-block__active")}}},n=(a(375),a(46)),c=Object(n.a)(o,(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("ClientOnly",[a("div",{staticClass:"theme-code-group"},[a("div",{staticClass:"theme-code-group__nav"},[a("ul",{staticClass:"theme-code-group__ul"},e._l(e.codeTabs,(function(t,o){return a("li",{key:t.title,staticClass:"theme-code-group__li"},[a("button",{staticClass:"theme-code-group__nav-tab",class:{"theme-code-group__nav-tab-active":o===e.activeCodeTabIndex},on:{click:function(t){return e.changeCodeTab(o)}}},[e._v("\n "+e._s(t.title)+"\n ")])])})),0)]),e._v(" "),e._t("default"),e._v(" "),e.codeTabs.length<1?a("pre",{staticClass:"pre-blank"},[e._v("// Make sure to add code blocks to your code group")]):e._e()],2)])}),[],!1,null,"deefee04",null);t.default=c.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/6.7dd3e1f3.js b/docs/assets/js/6.7a505dc8.js similarity index 81% rename from docs/assets/js/6.7dd3e1f3.js rename to docs/assets/js/6.7a505dc8.js index 14d83c1afd..0584a3dfe9 100644 --- a/docs/assets/js/6.7dd3e1f3.js +++ b/docs/assets/js/6.7a505dc8.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[6],{377:function(t,e,s){"use strict";s.r(e);var n=["There's nothing here.","How did we get here?","That's a Four-Oh-Four.","Looks like we've got some broken links."],o={methods:{getMsg:function(){return n[Math.floor(Math.random()*n.length)]}}},i=s(46),h=Object(i.a)(o,(function(){var t=this.$createElement,e=this._self._c||t;return e("div",{staticClass:"theme-container"},[e("div",{staticClass:"theme-default-content"},[e("h1",[this._v("404")]),this._v(" "),e("blockquote",[this._v(this._s(this.getMsg()))]),this._v(" "),e("RouterLink",{attrs:{to:"/"}},[this._v("\n Take me home.\n ")])],1)])}),[],!1,null,null,null);e.default=h.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[6],{389:function(t,e,s){"use strict";s.r(e);var n=["There's nothing here.","How did we get here?","That's a Four-Oh-Four.","Looks like we've got some broken links."],o={methods:{getMsg:function(){return n[Math.floor(Math.random()*n.length)]}}},i=s(54),h=Object(i.a)(o,(function(){var t=this.$createElement,e=this._self._c||t;return e("div",{staticClass:"theme-container"},[e("div",{staticClass:"theme-default-content"},[e("h1",[this._v("404")]),this._v(" "),e("blockquote",[this._v(this._s(this.getMsg()))]),this._v(" "),e("RouterLink",{attrs:{to:"/"}},[this._v("\n Take me home.\n ")])],1)])}),[],!1,null,null,null);e.default=h.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/7.00cd415f.js b/docs/assets/js/7.1ebac3c6.js similarity index 58% rename from docs/assets/js/7.00cd415f.js rename to docs/assets/js/7.1ebac3c6.js index 69862e9dc7..960ac13516 100644 --- a/docs/assets/js/7.00cd415f.js +++ b/docs/assets/js/7.1ebac3c6.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[7],{380:function(t,e,n){"use strict";n.r(e);var s=n(46),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[7],{392:function(t,e,n){"use strict";n.r(e);var s=n(54),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/8.17de77bc.js b/docs/assets/js/8.709919e3.js similarity index 94% rename from docs/assets/js/8.17de77bc.js rename to docs/assets/js/8.709919e3.js index fef3b892d8..a501763838 100644 --- a/docs/assets/js/8.17de77bc.js +++ b/docs/assets/js/8.709919e3.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[8],{383:function(e,r,t){"use strict";t.r(r);var n=t(46),a=Object(n.a)({},(function(){var e=this,r=e.$createElement,t=e._self._c||r;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"about"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#about"}},[e._v("#")]),e._v(" About")]),e._v(" "),t("p",[e._v("Caliban is a project developed by Pierre Ricadat aka "),t("a",{attrs:{href:"https://github.com/ghostdogpr",target:"_blank",rel:"noopener noreferrer"}},[e._v("@ghostdogpr"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[e._v("The name is inspired by the SF novel and tv series "),t("a",{attrs:{href:"https://en.wikipedia.org/wiki/Caliban%27s_War",target:"_blank",rel:"noopener noreferrer"}},[e._v("The Expanse"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[t("strong",[e._v("Thanks")]),e._v(":")]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://github.com/deckerst",target:"_blank",rel:"noopener noreferrer"}},[e._v("@deckerst"),t("OutboundLink")],1),e._v(" for the logo")]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/yoohaemin",target:"_blank",rel:"noopener noreferrer"}},[e._v("@yoohaemin"),t("OutboundLink")],1),e._v(", "),t("a",{attrs:{href:"https://github.com/adamgfraser",target:"_blank",rel:"noopener noreferrer"}},[e._v("@adamgfraser"),t("OutboundLink")],1),e._v(" and "),t("a",{attrs:{href:"https://github.com/jdegoes",target:"_blank",rel:"noopener noreferrer"}},[e._v("@jdegoes"),t("OutboundLink")],1),e._v(" for the early feedback")]),e._v(" "),t("li",[e._v("the "),t("a",{attrs:{href:"https://morpheusgraphql.com/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Morpheus"),t("OutboundLink")],1),e._v(" library in Haskell for the inspiration leading to the GraphQL backend implementation")]),e._v(" "),t("li",[e._v("the "),t("a",{attrs:{href:"https://github.com/dillonkearns/elm-graphql",target:"_blank",rel:"noopener noreferrer"}},[e._v("elm-graphql"),t("OutboundLink")],1),e._v(" library for the inspiration leading to the GraphQL client implementation")]),e._v(" "),t("li",[e._v("all Caliban's "),t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/graphs/contributors",target:"_blank",rel:"noopener noreferrer"}},[e._v("contributors"),t("OutboundLink")],1),e._v("!")])])])}),[],!1,null,null,null);r.default=a.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[8],{393:function(e,r,t){"use strict";t.r(r);var n=t(54),a=Object(n.a)({},(function(){var e=this,r=e.$createElement,t=e._self._c||r;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"about"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#about"}},[e._v("#")]),e._v(" About")]),e._v(" "),t("p",[e._v("Caliban is a project developed by Pierre Ricadat aka "),t("a",{attrs:{href:"https://github.com/ghostdogpr",target:"_blank",rel:"noopener noreferrer"}},[e._v("@ghostdogpr"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[e._v("The name is inspired by the SF novel and tv series "),t("a",{attrs:{href:"https://en.wikipedia.org/wiki/Caliban%27s_War",target:"_blank",rel:"noopener noreferrer"}},[e._v("The Expanse"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[t("strong",[e._v("Thanks")]),e._v(":")]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://github.com/deckerst",target:"_blank",rel:"noopener noreferrer"}},[e._v("@deckerst"),t("OutboundLink")],1),e._v(" for the logo")]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/yoohaemin",target:"_blank",rel:"noopener noreferrer"}},[e._v("@yoohaemin"),t("OutboundLink")],1),e._v(", "),t("a",{attrs:{href:"https://github.com/adamgfraser",target:"_blank",rel:"noopener noreferrer"}},[e._v("@adamgfraser"),t("OutboundLink")],1),e._v(" and "),t("a",{attrs:{href:"https://github.com/jdegoes",target:"_blank",rel:"noopener noreferrer"}},[e._v("@jdegoes"),t("OutboundLink")],1),e._v(" for the early feedback")]),e._v(" "),t("li",[e._v("the "),t("a",{attrs:{href:"https://morpheusgraphql.com/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Morpheus"),t("OutboundLink")],1),e._v(" library in Haskell for the inspiration leading to the GraphQL backend implementation")]),e._v(" "),t("li",[e._v("the "),t("a",{attrs:{href:"https://github.com/dillonkearns/elm-graphql",target:"_blank",rel:"noopener noreferrer"}},[e._v("elm-graphql"),t("OutboundLink")],1),e._v(" library for the inspiration leading to the GraphQL client implementation")]),e._v(" "),t("li",[e._v("all Caliban's "),t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/graphs/contributors",target:"_blank",rel:"noopener noreferrer"}},[e._v("contributors"),t("OutboundLink")],1),e._v("!")])])])}),[],!1,null,null,null);r.default=a.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/9.3d572142.js b/docs/assets/js/9.8f91e237.js similarity index 99% rename from docs/assets/js/9.3d572142.js rename to docs/assets/js/9.8f91e237.js index 5bdf3566aa..868032135e 100644 --- a/docs/assets/js/9.3d572142.js +++ b/docs/assets/js/9.8f91e237.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[9],{381:function(t,a,s){"use strict";s.r(a);var e=s(46),r=Object(e.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"getting-started"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#getting-started"}},[t._v("#")]),t._v(" Getting Started")]),t._v(" "),s("p",[s("strong",[t._v("Caliban")]),t._v(" is a purely functional library for creating GraphQL servers and clients in Scala.")]),t._v(" "),s("p",[t._v("For more details on Caliban Client, see the "),s("RouterLink",{attrs:{to:"/docs/client.html"}},[t._v("dedicated section")]),t._v(". The rest of this page is about the backend part of the library.")],1),t._v(" "),s("p",[t._v("The design principles of Caliban are the following:")]),t._v(" "),s("ul",[s("li",[s("strong",[t._v("pure interface")]),t._v(": errors and effects are returned explicitly (no exceptions thrown), all returned types are referentially transparent (no usage of "),s("code",[t._v("Future")]),t._v(").")]),t._v(" "),s("li",[s("strong",[t._v("minimal amount of boilerplate")]),t._v(": no need to manually define a schema for every type in your API. Let the compiler do the boring work.")]),t._v(" "),s("li",[s("strong",[t._v("excellent interoperability")]),t._v(": out-of-the-box support for major HTTP server libraries ("),s("a",{attrs:{href:"https://http4s.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("http4s"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://doc.akka.io/docs/akka-http/current/index.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Akka HTTP"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://www.playframework.com/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Play"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/finagle/finch",target:"_blank",rel:"noopener noreferrer"}},[t._v("Finch"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/dream11/zio-http",target:"_blank",rel:"noopener noreferrer"}},[t._v("ZIO HTTP"),s("OutboundLink")],1),t._v("), effect types (Future, "),s("a",{attrs:{href:"https://zio.dev/",target:"_blank",rel:"noopener noreferrer"}},[t._v("ZIO"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://typelevel.org/cats-effect/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Cats Effect"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://monix.io/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Monix"),s("OutboundLink")],1),t._v("), Json libraries ("),s("a",{attrs:{href:"https://circe.github.io/circe/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Circe"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/playframework/play-json",target:"_blank",rel:"noopener noreferrer"}},[t._v("Play Json"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/zio/zio-json",target:"_blank",rel:"noopener noreferrer"}},[t._v("ZIO Json"),s("OutboundLink")],1),t._v("), various integrations ("),s("a",{attrs:{href:"https://github.com/apollographql/apollo-tracing",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Tracing"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://www.apollographql.com/docs/federation/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Federation"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://tapir.softwaremill.com/en/latest/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Tapir"),s("OutboundLink")],1),t._v(", etc.) and more.")])]),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("To use "),s("code",[t._v("caliban")]),t._v(", add the following line in your "),s("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v('libraryDependencies += "com.github.ghostdogpr" %% "caliban" % "1.2.1"\n')])])]),s("p",[t._v("The following modules are optional:")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v('libraryDependencies += "com.github.ghostdogpr" %% "caliban-http4s" % "1.2.1" // routes for http4s\nlibraryDependencies += "com.github.ghostdogpr" %% "caliban-akka-http" % "1.2.1" // routes for akka-http\nlibraryDependencies += "com.github.ghostdogpr" %% "caliban-play" % "1.2.1" // routes for play\nlibraryDependencies += "com.github.ghostdogpr" %% "caliban-finch" % "1.2.1" // routes for finch\nlibraryDependencies += "com.github.ghostdogpr" %% "caliban-zio-http" % "1.2.1" // routes for zio-http\nlibraryDependencies += "com.github.ghostdogpr" %% "caliban-cats" % "1.2.1" // interop with cats effect\nlibraryDependencies += "com.github.ghostdogpr" %% "caliban-monix" % "1.2.1" // interop with monix\nlibraryDependencies += "com.github.ghostdogpr" %% "caliban-tapir" % "1.2.1" // interop with tapir\nlibraryDependencies += "com.github.ghostdogpr" %% "caliban-federation" % "1.2.1" // interop with apollo federation\n')])])]),s("h2",{attrs:{id:"a-simple-example"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#a-simple-example"}},[t._v("#")]),t._v(" A simple example")]),t._v(" "),s("p",[t._v("Creating a GraphQL API with Caliban is as simple as creating a case class. Indeed, the whole GraphQL schema will be derived from a case class structure (its fields and the other types it references), and the resolver is just an instance of that case class.")]),t._v(" "),s("p",[t._v("Let's say we have a class "),s("code",[t._v("Character")]),t._v(" and 2 functions: "),s("code",[t._v("getCharacters")]),t._v(" and "),s("code",[t._v("getCharacter")]),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("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),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(" age"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" getCharacters"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),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("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" getCharacter"),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(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),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("Let's create a case class named "),s("code",[t._v("Queries")]),t._v(" that will represent our API, with 2 fields named and modeled after the functions we want to expose (a "),s("em",[t._v("record of functions")]),t._v("). We then create a value of this class that calls our actual functions. This is our resolver.")]),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 comment"}},[t._v("// schema")]),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(" CharacterName"),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"),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("characters"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n character"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CharacterName "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" Option"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),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("// resolver")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" queries "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("getCharacters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" args "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" getCharacter"),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(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("The next step is creating our GraphQL API definition. First, we wrap our query resolver inside a "),s("code",[t._v("RootResolver")]),t._v(", the root object that contains queries, mutations and subscriptions. Only queries are mandatory.\nThen we can call the "),s("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(" "),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("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("GraphQL"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("graphQL\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("RootResolver\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("(")]),t._v("RootResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("You can use "),s("code",[t._v("api.render")]),t._v(" to visualize the schema generated, in this case:")]),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("type")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("age")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("Int")]),s("span",{pre:!0,attrs:{class:"token operator"}},[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("type")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Queries")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("characters")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("character")]),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(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),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 class-name"}},[t._v("Character")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("In order to process requests, you need to turn your API into an interpreter, which can be done easily by calling "),s("code",[t._v(".interpreter")]),t._v(".\nAn interpreter is a light wrapper around the API definition that allows plugging in some middleware and possibly modifying the environment and error types (see "),s("RouterLink",{attrs:{to:"/docs/middleware.html"}},[t._v("Middleware")]),t._v(" for more info).\nCreating the interpreter may fail with a "),s("code",[t._v("ValidationError")]),t._v(" if some type is found invalid.")],1),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("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n interpreter "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interpreter\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(" interpreter\n")])])]),s("p",[t._v("Now you can call "),s("code",[t._v("interpreter.execute")]),t._v(" with a given GraphQL query, and you will get an "),s("code",[t._v("ZIO[R, Nothing, GraphQLResponse[CalibanError]]")]),t._v(" as a response, with "),s("code",[t._v("GraphQLResponse")]),t._v(" defined as follows:")]),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(" GraphQLResponse"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v("E"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("data"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ResponseValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" errors"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("E"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("Use "),s("code",[t._v("ResponseValue#toString")]),t._v(" to get the JSON representation of the result.")]),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(" query "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token triple-quoted-string string"}},[t._v('"""\n {\n characters {\n name\n }\n }"""')]),t._v("\n\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 result "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" interpreter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("execute"),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("\n _ "),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("console"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("putStrLn"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),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"),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("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("A "),s("code",[t._v("CalibanError")]),t._v(" can be:")]),t._v(" "),s("ul",[s("li",[t._v("a "),s("code",[t._v("ParsingError")]),t._v(": the query has invalid syntax")]),t._v(" "),s("li",[t._v("a "),s("code",[t._v("ValidationError")]),t._v(": the query was parsed but does not match the schema")]),t._v(" "),s("li",[t._v("an "),s("code",[t._v("ExecutionError")]),t._v(": an error happened while executing the query")])]),t._v(" "),s("p",[t._v("Caliban itself is not tied to any web framework, you are free to expose this function using the protocol and library of your choice. The "),s("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/adapters/http4s",target:"_blank",rel:"noopener noreferrer"}},[t._v("caliban-http4s"),s("OutboundLink")],1),t._v(" module provides an "),s("code",[t._v("Http4sAdapter")]),t._v(" that exposes an interpreter over HTTP and WebSocket using http4s. There are also similar adapters for Akka HTTP, Play, Finch and zio-http.")]),t._v(" "),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("Combining GraphQL APIs")]),t._v(" "),s("p",[t._v("You don't have to define all your root fields into a single case class: you can use smaller case classes and combine "),s("code",[t._v("GraphQL")]),t._v(" objects using the "),s("code",[t._v("|+|")]),t._v(" operator.")]),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(" api1 "),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 punctuation"}},[t._v(".")]),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("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api2 "),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 punctuation"}},[t._v(".")]),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("\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(" api1 "),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(" api2\n")])])]),s("p",[t._v("You can use "),s("code",[t._v(".rename")]),t._v(" to change the names of the generated root types.")])]),t._v(" "),s("h2",{attrs:{id:"mutations"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#mutations"}},[t._v("#")]),t._v(" Mutations")]),t._v(" "),s("p",[t._v("Creating mutations is the same as queries, except you pass them as the second argument to "),s("code",[t._v("RootResolver")]),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("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" CharacterArgs"),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"),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(" Mutations"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("deleteCharacter"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CharacterArgs "),s("span",{pre:!0,attrs:{class:"token keyword"}},[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("Boolean")]),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 keyword"}},[t._v("val")]),t._v(" mutations "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Mutations"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\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("(")]),t._v("RootResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" mutations"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h2",{attrs:{id:"subscriptions"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#subscriptions"}},[t._v("#")]),t._v(" Subscriptions")]),t._v(" "),s("p",[t._v("Similarly, subscriptions are passed as the third argument to "),s("code",[t._v("RootResolver")]),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("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Subscriptions"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("deletedCharacter"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ZStream"),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 builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Character"),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 keyword"}},[t._v("val")]),t._v(" subscriptions "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Subscriptions"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\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("(")]),t._v("RootResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" mutations"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" subscriptions"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("All the fields of the subscription root case class MUST return "),s("code",[t._v("ZStream")]),t._v(" or "),s("code",[t._v("? => ZStream")]),t._v(" objects. When a subscription request is received, an output stream of "),s("code",[t._v("ResponseValue")]),t._v(" (a "),s("code",[t._v("StreamValue")]),t._v(") will be returned wrapped inside an "),s("code",[t._v("ObjectValue")]),t._v(".")])])}),[],!1,null,null,null);a.default=r.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[9],{394:function(t,a,s){"use strict";s.r(a);var e=s(54),r=Object(e.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"getting-started"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#getting-started"}},[t._v("#")]),t._v(" Getting Started")]),t._v(" "),s("p",[s("strong",[t._v("Caliban")]),t._v(" is a purely functional library for creating GraphQL servers and clients in Scala.")]),t._v(" "),s("p",[t._v("For more details on Caliban Client, see the "),s("RouterLink",{attrs:{to:"/docs/client.html"}},[t._v("dedicated section")]),t._v(". The rest of this page is about the backend part of the library.")],1),t._v(" "),s("p",[t._v("The design principles of Caliban are the following:")]),t._v(" "),s("ul",[s("li",[s("strong",[t._v("pure interface")]),t._v(": errors and effects are returned explicitly (no exceptions thrown), all returned types are referentially transparent (no usage of "),s("code",[t._v("Future")]),t._v(").")]),t._v(" "),s("li",[s("strong",[t._v("minimal amount of boilerplate")]),t._v(": no need to manually define a schema for every type in your API. Let the compiler do the boring work.")]),t._v(" "),s("li",[s("strong",[t._v("excellent interoperability")]),t._v(": out-of-the-box support for major HTTP server libraries ("),s("a",{attrs:{href:"https://http4s.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("http4s"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://doc.akka.io/docs/akka-http/current/index.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Akka HTTP"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://www.playframework.com/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Play"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/finagle/finch",target:"_blank",rel:"noopener noreferrer"}},[t._v("Finch"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/dream11/zio-http",target:"_blank",rel:"noopener noreferrer"}},[t._v("ZIO HTTP"),s("OutboundLink")],1),t._v("), effect types (Future, "),s("a",{attrs:{href:"https://zio.dev/",target:"_blank",rel:"noopener noreferrer"}},[t._v("ZIO"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://typelevel.org/cats-effect/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Cats Effect"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://monix.io/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Monix"),s("OutboundLink")],1),t._v("), Json libraries ("),s("a",{attrs:{href:"https://circe.github.io/circe/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Circe"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/playframework/play-json",target:"_blank",rel:"noopener noreferrer"}},[t._v("Play Json"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/zio/zio-json",target:"_blank",rel:"noopener noreferrer"}},[t._v("ZIO Json"),s("OutboundLink")],1),t._v("), various integrations ("),s("a",{attrs:{href:"https://github.com/apollographql/apollo-tracing",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Tracing"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://www.apollographql.com/docs/federation/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Federation"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://tapir.softwaremill.com/en/latest/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Tapir"),s("OutboundLink")],1),t._v(", etc.) and more.")])]),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("To use "),s("code",[t._v("caliban")]),t._v(", add the following line in your "),s("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v('libraryDependencies += "com.github.ghostdogpr" %% "caliban" % "1.2.1"\n')])])]),s("p",[t._v("The following modules are optional:")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v('libraryDependencies += "com.github.ghostdogpr" %% "caliban-http4s" % "1.2.1" // routes for http4s\nlibraryDependencies += "com.github.ghostdogpr" %% "caliban-akka-http" % "1.2.1" // routes for akka-http\nlibraryDependencies += "com.github.ghostdogpr" %% "caliban-play" % "1.2.1" // routes for play\nlibraryDependencies += "com.github.ghostdogpr" %% "caliban-finch" % "1.2.1" // routes for finch\nlibraryDependencies += "com.github.ghostdogpr" %% "caliban-zio-http" % "1.2.1" // routes for zio-http\nlibraryDependencies += "com.github.ghostdogpr" %% "caliban-cats" % "1.2.1" // interop with cats effect\nlibraryDependencies += "com.github.ghostdogpr" %% "caliban-monix" % "1.2.1" // interop with monix\nlibraryDependencies += "com.github.ghostdogpr" %% "caliban-tapir" % "1.2.1" // interop with tapir\nlibraryDependencies += "com.github.ghostdogpr" %% "caliban-federation" % "1.2.1" // interop with apollo federation\n')])])]),s("h2",{attrs:{id:"a-simple-example"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#a-simple-example"}},[t._v("#")]),t._v(" A simple example")]),t._v(" "),s("p",[t._v("Creating a GraphQL API with Caliban is as simple as creating a case class. Indeed, the whole GraphQL schema will be derived from a case class structure (its fields and the other types it references), and the resolver is just an instance of that case class.")]),t._v(" "),s("p",[t._v("Let's say we have a class "),s("code",[t._v("Character")]),t._v(" and 2 functions: "),s("code",[t._v("getCharacters")]),t._v(" and "),s("code",[t._v("getCharacter")]),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("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),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(" age"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" getCharacters"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),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("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" getCharacter"),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(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),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("Let's create a case class named "),s("code",[t._v("Queries")]),t._v(" that will represent our API, with 2 fields named and modeled after the functions we want to expose (a "),s("em",[t._v("record of functions")]),t._v("). We then create a value of this class that calls our actual functions. This is our resolver.")]),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 comment"}},[t._v("// schema")]),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(" CharacterName"),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"),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("characters"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n character"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CharacterName "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" Option"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),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("// resolver")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" queries "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("getCharacters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" args "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" getCharacter"),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(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("The next step is creating our GraphQL API definition. First, we wrap our query resolver inside a "),s("code",[t._v("RootResolver")]),t._v(", the root object that contains queries, mutations and subscriptions. Only queries are mandatory.\nThen we can call the "),s("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(" "),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("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("GraphQL"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("graphQL\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("RootResolver\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("(")]),t._v("RootResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("You can use "),s("code",[t._v("api.render")]),t._v(" to visualize the schema generated, in this case:")]),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("type")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("age")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("Int")]),s("span",{pre:!0,attrs:{class:"token operator"}},[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("type")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Queries")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("characters")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("character")]),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(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),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 class-name"}},[t._v("Character")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("In order to process requests, you need to turn your API into an interpreter, which can be done easily by calling "),s("code",[t._v(".interpreter")]),t._v(".\nAn interpreter is a light wrapper around the API definition that allows plugging in some middleware and possibly modifying the environment and error types (see "),s("RouterLink",{attrs:{to:"/docs/middleware.html"}},[t._v("Middleware")]),t._v(" for more info).\nCreating the interpreter may fail with a "),s("code",[t._v("ValidationError")]),t._v(" if some type is found invalid.")],1),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("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n interpreter "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interpreter\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(" interpreter\n")])])]),s("p",[t._v("Now you can call "),s("code",[t._v("interpreter.execute")]),t._v(" with a given GraphQL query, and you will get an "),s("code",[t._v("ZIO[R, Nothing, GraphQLResponse[CalibanError]]")]),t._v(" as a response, with "),s("code",[t._v("GraphQLResponse")]),t._v(" defined as follows:")]),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(" GraphQLResponse"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v("E"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("data"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ResponseValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" errors"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("E"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("Use "),s("code",[t._v("ResponseValue#toString")]),t._v(" to get the JSON representation of the result.")]),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(" query "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token triple-quoted-string string"}},[t._v('"""\n {\n characters {\n name\n }\n }"""')]),t._v("\n\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 result "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" interpreter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("execute"),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("\n _ "),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("console"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("putStrLn"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),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"),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("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("A "),s("code",[t._v("CalibanError")]),t._v(" can be:")]),t._v(" "),s("ul",[s("li",[t._v("a "),s("code",[t._v("ParsingError")]),t._v(": the query has invalid syntax")]),t._v(" "),s("li",[t._v("a "),s("code",[t._v("ValidationError")]),t._v(": the query was parsed but does not match the schema")]),t._v(" "),s("li",[t._v("an "),s("code",[t._v("ExecutionError")]),t._v(": an error happened while executing the query")])]),t._v(" "),s("p",[t._v("Caliban itself is not tied to any web framework, you are free to expose this function using the protocol and library of your choice. The "),s("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/master/adapters/http4s",target:"_blank",rel:"noopener noreferrer"}},[t._v("caliban-http4s"),s("OutboundLink")],1),t._v(" module provides an "),s("code",[t._v("Http4sAdapter")]),t._v(" that exposes an interpreter over HTTP and WebSocket using http4s. There are also similar adapters for Akka HTTP, Play, Finch and zio-http.")]),t._v(" "),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("Combining GraphQL APIs")]),t._v(" "),s("p",[t._v("You don't have to define all your root fields into a single case class: you can use smaller case classes and combine "),s("code",[t._v("GraphQL")]),t._v(" objects using the "),s("code",[t._v("|+|")]),t._v(" operator.")]),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(" api1 "),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 punctuation"}},[t._v(".")]),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("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api2 "),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 punctuation"}},[t._v(".")]),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("\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(" api1 "),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(" api2\n")])])]),s("p",[t._v("You can use "),s("code",[t._v(".rename")]),t._v(" to change the names of the generated root types.")])]),t._v(" "),s("h2",{attrs:{id:"mutations"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#mutations"}},[t._v("#")]),t._v(" Mutations")]),t._v(" "),s("p",[t._v("Creating mutations is the same as queries, except you pass them as the second argument to "),s("code",[t._v("RootResolver")]),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("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" CharacterArgs"),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"),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(" Mutations"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("deleteCharacter"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CharacterArgs "),s("span",{pre:!0,attrs:{class:"token keyword"}},[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("Boolean")]),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 keyword"}},[t._v("val")]),t._v(" mutations "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Mutations"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\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("(")]),t._v("RootResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" mutations"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h2",{attrs:{id:"subscriptions"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#subscriptions"}},[t._v("#")]),t._v(" Subscriptions")]),t._v(" "),s("p",[t._v("Similarly, subscriptions are passed as the third argument to "),s("code",[t._v("RootResolver")]),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("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Subscriptions"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("deletedCharacter"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ZStream"),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 builtin"}},[t._v("Nothing")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Character"),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 keyword"}},[t._v("val")]),t._v(" subscriptions "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Subscriptions"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\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("(")]),t._v("RootResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" mutations"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" subscriptions"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("All the fields of the subscription root case class MUST return "),s("code",[t._v("ZStream")]),t._v(" or "),s("code",[t._v("? => ZStream")]),t._v(" objects. When a subscription request is received, an output stream of "),s("code",[t._v("ResponseValue")]),t._v(" (a "),s("code",[t._v("StreamValue")]),t._v(") will be returned wrapped inside an "),s("code",[t._v("ObjectValue")]),t._v(".")])])}),[],!1,null,null,null);a.default=r.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/app.bdde3623.js b/docs/assets/js/app.bdde3623.js deleted file mode 100644 index 12dfa39668..0000000000 --- a/docs/assets/js/app.bdde3623.js +++ /dev/null @@ -1,8 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[0],[]]);!function(t){function e(e){for(var r,a,c=e[0],u=e[1],s=e[2],l=0,p=[];l=n.length?{value:void 0,done:!0}:(t=r(n,o),e.index+=t.length,{value:t,done:!1})}))},function(t,e,n){var r=n(2),o=n(4),i=n(8),a=n(21),c=n(82),u=n(58),s=n(27),f=n(78).CONFIGURABLE,l=s.get,p=s.enforce,h=String(String).split("String");(t.exports=function(t,e,n,u){var s,l=!!u&&!!u.unsafe,d=!!u&&!!u.enumerable,v=!!u&&!!u.noTargetGet,y=u&&void 0!==u.name?u.name:e;o(n)&&("Symbol("===String(y).slice(0,7)&&(y="["+String(y).replace(/^Symbol\(([^)]*)\)/,"$1")+"]"),(!i(n,"name")||f&&n.name!==y)&&a(n,"name",y),(s=p(n)).source||(s.source=h.join("string"==typeof y?y:""))),t!==r?(l?!v&&t[e]&&(d=!0):delete t[e],d?t[e]=n:a(t,e,n)):d?t[e]=n:c(e,n)})(Function.prototype,"toString",(function(){return o(this)&&l(this).source||u(this)}))},function(t,e){var n=Array.isArray;t.exports=n},function(t,e,n){var r=n(34),o=n(26);t.exports=function(t){return r(o(t))}},function(t,e,n){var r=n(2),o=n(136),i=n(137),a=n(112),c=n(21),u=n(3),s=u("iterator"),f=u("toStringTag"),l=a.values,p=function(t,e){if(t){if(t[s]!==l)try{c(t,s,l)}catch(e){t[s]=l}if(t[f]||c(t,f,e),o[e])for(var n in a)if(t[n]!==a[n])try{c(t,n,a[n])}catch(e){t[n]=a[n]}}};for(var h in o)p(r[h]&&r[h].prototype,h);p(i,"DOMTokenList")},function(t,e,n){var r=n(148),o="object"==typeof self&&self&&self.Object===Object&&self,i=r||o||Function("return this")();t.exports=i},function(t,e,n){var r=n(61);t.exports=function(t){if("Symbol"===r(t))throw TypeError("Cannot convert a Symbol value to a string");return String(t)}},function(t,e){t.exports=!1},function(t,e,n){var r=n(7),o=n(9),i=n(38);t.exports=r?function(t,e,n){return o.f(t,e,i(1,n))}:function(t,e,n){return t[e]=n,t}},function(t,e,n){var r,o=n(6),i=n(192),a=n(86),c=n(36),u=n(118),s=n(53),f=n(57),l=f("IE_PROTO"),p=function(){},h=function(t){return" + diff --git a/docs/docs/examples.html b/docs/docs/examples.html index 36adcd51a9..10be886a48 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 d99e8aa8ed..19294b2c50 100644 --- a/docs/docs/federation.html +++ b/docs/docs/federation.html @@ -8,7 +8,7 @@ - + @@ -86,6 +86,6 @@ β†’

- + diff --git a/docs/docs/index.html b/docs/docs/index.html index d4183eb3a3..8fc4f499bb 100644 --- a/docs/docs/index.html +++ b/docs/docs/index.html @@ -8,7 +8,7 @@ - + @@ -104,6 +104,6 @@ β†’

- + diff --git a/docs/docs/interop.html b/docs/docs/interop.html index 828885fe74..6ef7df05b1 100644 --- a/docs/docs/interop.html +++ b/docs/docs/interop.html @@ -8,7 +8,7 @@ - + @@ -127,6 +127,6 @@ β†’

- + diff --git a/docs/docs/introspection.html b/docs/docs/introspection.html index da7c9fc233..21ec8f9724 100644 --- a/docs/docs/introspection.html +++ b/docs/docs/introspection.html @@ -8,7 +8,7 @@ - + @@ -45,6 +45,6 @@ β†’

- + diff --git a/docs/docs/middleware.html b/docs/docs/middleware.html index 3e0d55296e..784dda0afb 100644 --- a/docs/docs/middleware.html +++ b/docs/docs/middleware.html @@ -8,7 +8,7 @@ - + @@ -105,6 +105,6 @@ β†’

- + diff --git a/docs/docs/optimization.html b/docs/docs/optimization.html index b40cbab03f..06096c2cba 100644 --- a/docs/docs/optimization.html +++ b/docs/docs/optimization.html @@ -8,7 +8,7 @@ - + @@ -100,6 +100,6 @@ β†’

- + diff --git a/docs/docs/schema.html b/docs/docs/schema.html index aa0ca68a68..16d2d79356 100644 --- a/docs/docs/schema.html +++ b/docs/docs/schema.html @@ -8,7 +8,7 @@ - + @@ -107,9 +107,10 @@ character: CharacterName => RIO[Console, Character])

If you don't use ZIO environment (R = Any), there is nothing special to do to get it working.

If you require a ZIO environment, you will need to have the content of caliban.schema.GenericSchema[R] for your custom R in scope when you call graphQL(...).

object schema extends GenericSchema[MyEnv]
 import schema._
+import schema.gen // Necessary for scala 3 due to https://docs.scala-lang.org/scala3/book/ca-given-imports.html
 

Note: If you ever need to declare schemas explicitly (by calling gen directly, as explained above), and you require a ZIO environment (explained in this section), then you must use the gen from this object schema. If you call gen to derive schemas in the same module and you import schema._ at the top of this module, -you'd be fine. However, if you derive schemas in a separate module, then make sure you import this schema object in that module so that you'll be using the gen from the schema object.

# Annotations

Caliban supports a few annotations to enrich data types:

  • @GQLName("name") allows you to specify a different name for a data type or a field.
  • @GQLInputName("name") allows you to specify a different name for a data type used as an input (by default, the suffix Input is appended to the type name).
  • @GQLDescription("description") lets you provide a description for a data type or field. This description will be visible when your schema is introspected.
  • @GQLDeprecated("reason") allows deprecating a field or an enum value.
  • @GQLInterface to force a sealed trait generating an interface instead of a union.
  • @GQLDirective(directive: Directive) to add a directive to a field or type.
  • @GQLValueType 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.
  • @GQLDefault("defaultValue") 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.

# Java 8 Time types

Caliban provides implicit Schema types for the standard java.time types, by default these will use the +you'd be fine. However, if you derive schemas in a separate module, then make sure you import this schema object in that module so that you'll be using the gen from the schema object.

# Annotations

Caliban supports a few annotations to enrich data types:

  • @GQLName("name") allows you to specify a different name for a data type or a field.
  • @GQLInputName("name") allows you to specify a different name for a data type used as an input (by default, the suffix Input is appended to the type name).
  • @GQLDescription("description") lets you provide a description for a data type or field. This description will be visible when your schema is introspected.
  • @GQLDeprecated("reason") allows deprecating a field or an enum value.
  • @GQLInterface to force a sealed trait generating an interface instead of a union.
  • @GQLDirective(directive: Directive) to add a directive to a field or type.
  • @GQLValueType(isScalar) 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 isScalar is true, it will generate a scalar named after the case class (default: false).
  • @GQLDefault("defaultValue") 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.

# Java 8 Time types

Caliban provides implicit Schema types for the standard java.time types, by default these will use the ISO standard strings for serialization and deserialization. However, you can customize this behavior by using explicit constructor available under the ArgBuilder companion object. For instance, you can specify an instantEpoch to handle instants which are encoded using a Long from the standard java epoch time (January 1st 1970 00:00:00). @@ -169,6 +170,6 @@ β†’

- + diff --git a/docs/docs/stitching.html b/docs/docs/stitching.html index e267982796..bda601242a 100644 --- a/docs/docs/stitching.html +++ b/docs/docs/stitching.html @@ -8,7 +8,7 @@ - + @@ -175,6 +175,6 @@ β†’

- + diff --git a/docs/docs/tools.html b/docs/docs/tools.html index 9fa379510f..1713c026a6 100644 --- a/docs/docs/tools.html +++ b/docs/docs/tools.html @@ -8,7 +8,7 @@ - + @@ -75,6 +75,6 @@ β†’

- + diff --git a/docs/docs/validation.html b/docs/docs/validation.html index 3d1603b08e..de0d7a519e 100644 --- a/docs/docs/validation.html +++ b/docs/docs/validation.html @@ -8,7 +8,7 @@ - + @@ -54,6 +54,6 @@ β†’

- + diff --git a/docs/faq/index.html b/docs/faq/index.html index ec79b79d5b..d2daaa1f8e 100644 --- a/docs/faq/index.html +++ b/docs/faq/index.html @@ -8,7 +8,7 @@ - + @@ -57,6 +57,6 @@ Schema.customErrorEffectSchema((code: Int) => ExecutionError(s"Error code $code"))

With this implicit in scope, Caliban will know how to handle any IO[Int, A] effects. Caliban will automatically fill the error path and the error location inside ExecutionError if an error happens during the query execution.

- + diff --git a/docs/index.html b/docs/index.html index e1a7cb8717..ea29499361 100644 --- a/docs/index.html +++ b/docs/index.html @@ -8,7 +8,7 @@ - + @@ -43,6 +43,6 @@

Get Started β†’

Purely functional

All interfaces are pure and types are referentially transparent. Schemas are type safe and derived at compile time.

Minimal boilerplate

No need to manually define a schema for every type in your API. Let the compiler do the boring 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 6e53c8a737..a3f99a9d55 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

- +