From a6f78d710ea94500cba5e991ab003116780d072c Mon Sep 17 00:00:00 2001 From: Pierre Ricadat Date: Sat, 18 May 2024 09:27:02 +0000 Subject: [PATCH] [ci skip] update docs --- docs/404.html | 6 +- docs/about/index.html | 8 +- docs/altair.png | Bin 55646 -> 0 bytes .../js/{23.05b059b6.js => 23.cd7748bf.js} | 2 +- docs/assets/js/24.4e724191.js | 1 - docs/assets/js/24.d41ca9d3.js | 1 + docs/assets/js/25.693cf732.js | 1 - docs/assets/js/25.8e82221d.js | 1 + docs/assets/js/28.755a8b70.js | 1 + docs/assets/js/28.d0ed8364.js | 1 - docs/assets/js/30.cc13c839.js | 1 + docs/assets/js/30.fbe96632.js | 1 - docs/assets/js/31.86d5b347.js | 1 - .../js/{32.73130b5d.js => 31.c29a55e2.js} | 2 +- .../js/{33.b2f8ae12.js => 32.03eccd7b.js} | 2 +- .../js/{34.8425abc5.js => 33.bc31e9d4.js} | 2 +- .../js/{35.0a127519.js => 34.06413a27.js} | 2 +- .../js/{36.7450762f.js => 35.af875e74.js} | 2 +- docs/assets/js/36.86142689.js | 1 + docs/assets/js/37.9db4c004.js | 1 - docs/assets/js/37.ebe3c9ba.js | 1 + docs/assets/js/38.47b0ded6.js | 1 - docs/assets/js/38.81bab45a.js | 1 + docs/assets/js/39.956f0096.js | 1 - .../js/{40.f2a62c0d.js => 39.d3af0fd1.js} | 2 +- .../js/{41.52247050.js => 40.8a7ce965.js} | 2 +- .../js/{43.8339688b.js => 41.ab98ab0d.js} | 2 +- docs/assets/js/42.99036692.js | 1 - .../js/{44.e00ae25b.js => 42.b28d8bbd.js} | 2 +- .../js/{app.8293a53f.js => app.cd64229a.js} | 4 +- docs/docs/adapters.html | 24 ++--- docs/docs/client-codegen.html | 8 +- docs/docs/client.html | 12 +-- docs/docs/examples.html | 10 +-- docs/docs/federation.html | 12 +-- docs/docs/index.html | 85 ++++++------------ docs/docs/interop.html | 16 ++-- docs/docs/introspection.html | 50 ----------- docs/docs/laminext.html | 8 +- docs/docs/middleware.html | 40 ++++----- docs/docs/optimization.html | 14 +-- docs/docs/relay-connections.html | 10 +-- docs/docs/schema-comparison.html | 8 +- docs/docs/schema-reporting.html | 14 +-- docs/docs/schema.html | 43 ++++----- docs/docs/server-codegen.html | 38 ++++---- docs/docs/stitching.html | 8 +- docs/docs/tools.html | 8 +- docs/docs/validation.html | 59 ------------ docs/faq/index.html | 16 +++- docs/index.html | 10 +-- docs/resources/index.html | 8 +- 52 files changed, 204 insertions(+), 351 deletions(-) delete mode 100644 docs/altair.png rename docs/assets/js/{23.05b059b6.js => 23.cd7748bf.js} (97%) delete mode 100644 docs/assets/js/24.4e724191.js create mode 100644 docs/assets/js/24.d41ca9d3.js delete mode 100644 docs/assets/js/25.693cf732.js create mode 100644 docs/assets/js/25.8e82221d.js create mode 100644 docs/assets/js/28.755a8b70.js delete mode 100644 docs/assets/js/28.d0ed8364.js create mode 100644 docs/assets/js/30.cc13c839.js delete mode 100644 docs/assets/js/30.fbe96632.js delete mode 100644 docs/assets/js/31.86d5b347.js rename docs/assets/js/{32.73130b5d.js => 31.c29a55e2.js} (99%) rename docs/assets/js/{33.b2f8ae12.js => 32.03eccd7b.js} (60%) rename docs/assets/js/{34.8425abc5.js => 33.bc31e9d4.js} (99%) rename docs/assets/js/{35.0a127519.js => 34.06413a27.js} (99%) rename docs/assets/js/{36.7450762f.js => 35.af875e74.js} (99%) create mode 100644 docs/assets/js/36.86142689.js delete mode 100644 docs/assets/js/37.9db4c004.js create mode 100644 docs/assets/js/37.ebe3c9ba.js delete mode 100644 docs/assets/js/38.47b0ded6.js create mode 100644 docs/assets/js/38.81bab45a.js delete mode 100644 docs/assets/js/39.956f0096.js rename docs/assets/js/{40.f2a62c0d.js => 39.d3af0fd1.js} (99%) rename docs/assets/js/{41.52247050.js => 40.8a7ce965.js} (96%) rename docs/assets/js/{43.8339688b.js => 41.ab98ab0d.js} (94%) delete mode 100644 docs/assets/js/42.99036692.js rename docs/assets/js/{44.e00ae25b.js => 42.b28d8bbd.js} (98%) rename docs/assets/js/{app.8293a53f.js => app.cd64229a.js} (82%) delete mode 100644 docs/docs/introspection.html delete mode 100644 docs/docs/validation.html diff --git a/docs/404.html b/docs/404.html index 693dffd4e8..5187f31d87 100644 --- a/docs/404.html +++ b/docs/404.html @@ -8,13 +8,13 @@ - + -

404

Looks like we've got some broken links.
+ - + diff --git a/docs/about/index.html b/docs/about/index.html index 1e52654274..fde29b0ced 100644 --- a/docs/about/index.html +++ b/docs/about/index.html @@ -8,7 +8,7 @@ - + @@ -22,7 +22,7 @@ About

# About

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

Current maintainers:

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

Thanks:

- + diff --git a/docs/altair.png b/docs/altair.png deleted file mode 100644 index 7851133677b7cf918331c014e5e27a3be207abc6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55646 zcmeFZWmJ@38!xPMgQPS{w?Vg}bV+w3ISe7)AxL+Llz@nI4mEV6fHX6t(gO@RLvzOe zd7iT#_0w7FJ?osc-si*2toz<`@3{80ul!wil!lr-As!9hojZ336%}4+-noN8e&-Gv z1`ZbLPAPSOBBpL^* za+rUSk}1Da^6&MxW8!d}u@$2IPA}B3D6%vBz5f4QvWMs|3qoYxMn~gu^7Ch`tyxFK zNwV>OpRGFRqcR&r>_Lmw^Q7D+6xq+eK$B^!Ou>dTl_uO#QBiJ)d0Wt0x>`#?w&|*&jcDCOm?FcNM8KXmrYo zr4iiWCggB}HmXY9Ub%12*RkJyTljNkh3B^|2ziZPe;(X@bA7qKU6SXi-rhq~@Z z*VlJ6#GW@8iiy8=0jtWe=!tj>?DzVMz6YG+8|ZjXZAS^P$gl`$SW0qzzntt$D~oyT zu)KWvvesdmD@)v~a(A&+FE;>T(0n>$wCJ0s<`nJC{lFW zYnY8Ney^}Ono|s1Zhzu?V&`+V8o8+PF6ibs&uxSkG&LX3{}+R-sOPJW9VO=E(6>SG z`I?x{M6YD+o^)3jfs{NvJkHqs<^N(IMl?W6KO`lslIt*MiGqsC$yv-dp2xr?3DoYy(K=W> zi%Cr-7jEk&eGYjPdteEbIA2R~K1|ay<)jz)Oy%#m(&UM<)YVOg8MrQb%ubiSuG9OP zD=F?B@5yU#Z=al%wN0wd#=oBknakQLJopyzwnLI~z9ol$lv}R2(j`jk;OH zrE1t{JI0Vv)t$@_dEDX!=R?OPN_G9&uh9&UV)qr?B<6RHh`3UX(EcnolWxHnMDYK6GGG?%IT;XFIoW8cwgcWosTW-k!S?Cld$#Gvm0awzohR8 zPSx=5Bw1-9w+qThZ}eTCdD`_FSZx{iy|?!T5(Dxn=0vOf?!_Q;f`X1tn&Tr=&v_e5 zSq>ilFiev28s|72$E&Pk5KKsKVuS7bQ=9{fN};_wCaBlBRt=gzQ-SB^eRyCRfyHOF;7 zW2v9^v*y>!gk#E-ThIm4;Ya9qcIP%3jdy(lw4MEkS)7XVl*m?_L;z=jU^F$6)o`&{ zy8+;5{otQVesGTgkd=Pn;wS)8Z=al-yB`mjd}#>3+bRdMF;~BmjiHvl*ecwo+x4o4 ziC^y4EjH^j5a8pbrlmFKQc&JkQd1+U*x$K69}7xfZ1rl*WtqwD8tsa=0_%P459Edg zm@muvspzX`3@`>QV3K{kx;h@CYQ_HA<(r-vhe=tEj55*Mf}3r!oQ3`-D(K|@krRZn z+2AfTG=#u%ZnaU5ptSU|peX>1Nl(L#u!hiF&+IL~4yoQhO&|YG(>PqZEf zn$iX>K}#f08<+0QaDYk<((g=!lISkCTp5K09RBFrmjK|r72fUMiNqq`6>C4O01jo@ z=5Eup>dwMKET9kq3eWhN#76h}ZT^(x+^##sn}F9&8LkI(eP&S z8;>tHggdrF@n)()*YoW>B<9bE@rmX{<#wW0_xP`__dv^@�gSUhT*9Sx;=D#l4Q} z%!4ssJ1x&-f=C%Os&i>P13Z^z&^s%~La{sp5ViTey-{Q)vt zo<3g#eHj!z%Yc`)a7vQu{P0r_(Y^Y~P+9%*%`nWO-N5tj34v>)^MTy>3;HWv``FpM zy-t9$7{+WD?sn$iRO3Lj%t_H5z#3i$qM>T2IKz~NfDU!ye0e2MLgJ{*>{^MzZ}%}$ zdx>T@DVoru8tW4UOpTHAj)i&!80(@WFL0;v^rkwZ!sDpvXT10h22I;(I#m}+9;(k5 zrVXXA$6#VTO!I)vG-I_^)Rkn6eD|Wv?(1z5d2Q@u!ndS-G>xZ^zT3K?_@I)N`Q14bBs zQz4y)eB+dIBFPC`2nxMk}pC1^#Cfva#x4G+}BWz zV3Zt8o0;rv8Gr^d3rZADH!R`lmO}&TEuY2M^@+6SkOR-yhlvD6$6v?go+ za|Kgl*Yuq(&*Q?=KpcM4Zk5)3;bs5HQ_`9{SeU)8L!p5DnP;Da#wpo zJ=hQD#p{YBr#K&FJ3GnyPX1s$C+~0yd{TYQUb{Z!bh|j)OS&cH&U7Q@+1!07!QD&5 zo_i17?soI6d3+<#h@qkY2y1h%&zG++xoR}ADz2%#5OV4%Z@cr%>ayf;5iHr65SHsRM;>FxzJ zKL9@owW{~P7pkI>3YVbc_Ps{vT8`I}D_Dc)uy|diI)j2%&2mUY_L%Plgm~n4v+1Ye zN+tnE_)YN4yGE7U^fUPBteMv{Oxh}79kYIoGeVc=e96EzXI)AdA-^?_gU{A>G|XKY zEttu>UBIec&w!1nm8-<$;yE;PkIB&L^wpyS^c~m9d0WXo`$%|x5JC0Ah|%}kl8`CA z(dM~+6$#A5;+*t~61M7gzMj!~Cv|;#uFa>;Z+@4SvaR~T({#|P-|}T{)hb`$SlHgZ z|FmI48Xu0oM#r0RImy*Dl3jAUBcRO_YSqnz! zdi+gT-svlZ;9jIwn>&Fdyl37_d8Xk3jxJB8Ihf+P?I#>*wfbXZt!ZCE(PLgZG(Yi_KX1TL ze)qCO`dTsY_HsE!m3mIUW*(=F6tZ$cQz*o?>{#v#6+}2|@%Uag@Ev~7jWsGfafx1M zsJ0xaAaC6miR8;jE;4Gr6)?fQK6=BAR8qLH+j9T~w-COn0nhGmF% zm03aOZGj?@tfR5IJa%j6-j`906`%!Dq0!98%$Yww791b%9QVog?zWvWKIM{dR`=p=Nb{OAACb?Yy5B*i^EWF8@P;99Cfd)Lg%YQ?O7}e|%u{ zv1ZM3=SY<~`0g$UhrjVFjL@=Uw#oHpX!e{J5P`4!Ws7y3z**yRwPDtj?AQlZ0b=3f z<7>JoEy+zrSwtL7w=2;QV$Z7ik?4$`0?#zRIwo~lmhP%cU)S@Pv`q1Waxn_xp5xUWIHuh5rAAkx7O-Z`?7yZE4ZO(^FhX95CHlO2#8yed9RidR%MoPM- zt&cGalm-R{`-XeQyI18&&d*{{hS!p+y*;gJwopX~xZ&!{@tE}T-jwfy1+V3RN~*WQ zTH&W+)$@Wp3E{#L53dNyYxei7_8<*MXFn6fy;`NQIUtO`bzuHBkoJ;;GSY(2YsB2N-(jJ6%HQ4WuusZVj+$%OL$P}90X zHTyW_qiVU2aofn`vw2RGelg<%pG^4LT1{dZqA%t;^P9CVfSpiuzyTOTQd3dhl0(kL zFC)~i1)#pc>tfNv;Dm)ULS^3bgiZB53(CuIu13n{(94}$svnMtZql7^6(;m1D;WZD z{f3d>bS|w^8TDEfYs%1Ql42+Zq)pD&U(=r4=*!=Sdx~0qi`?f~4bZyK^%}M9hkLs@D|G5l6O znCdDaAx-l|ryDEFoo-YCI2L7?< zqq!?_h|CTU7GV0XtZZ!kn1Z`ap11l;J@GbRO&%BWq0!fe)py=~6R-%08qXzeyzMc8 z=P<*6w@$vZjjPdio?@3X0&M4dk86tFo}ZsrKC>rO91%C?cU&;CswwTGshRoQ&|ief z>|`ga6^;3jXFd;;x~-HTTeC_Osvq`?AkMQ?QW*K7mrkW(GfcwL%5!tttp`?qv$i9= z8Y`Q~V}uQum8aSq87vGg2Jt~!uRW?S2Sa5&_jN%v{^Xuj1_`ltA@MyXjC;lgzY9$N zG_(P2nborJwYlG>jHQW7e<^+MBv z`Zvw-%WxIokdY~P#-RJ~H!Bv^vkVI=@Rg*kAMsaTgm@$xc8QT`e+^Hf7##eZg(CgI zUwwt4qGdE|7OZ~_|ALe$pG5Jk&0l@}UtbE7&_s7*H4i_374HYO&3AuLq4VCottIf~ zJ<)hC5?>B)(zf5dfM4`W!GzFHO{`VSll*Q~{<6|E?)q}L(Eb(m`){xjgXI58u<^e! z-v5&Q|39Ji|8o2PS#FQt4u1aXW!hSr4t+|8+qaOgqfG%Re+E z9T=@f9$tDbT^Id@#%FZ|Q0r@(RX%UR=0l@VolLj*sPHUuZ)yCN*bHaX_o5ru#uYfzsYYx>}C=%iqHZB3Kx|^w~_+&(n3$qt*nW z!9aQ}b1M-(`f26Y0sCpiy~*25UGt zJ0&aDa*CzpI_TW}_T5H5><^uO2kjLm5-O@u&pZ}T4dJ3W*H$+ zJ-J^>o~kz#6Vo`-V&b<@9TOhExA-VFYI|{Q7&m~Gt^3hi;dFQ^@$CB0oK%$CG3T|- z(#G?wR!+0_L9XP5+JK`4VWQJ7XNMyreOTrGKYQO~k-HHVY#!C@kL*-UW-+-9bJ-|3 zgc5A$GU>&_xzSH04QpHS=Ll~0u6>KAR};{wsVk8mg6q5nqs0+eMy)3p5&`n z&1O=wxmXF`mbuLKInwjSj5*Z<11x*PqiK(ZZALfHwhO^%l~Zy-pGJ2y3KiKWTLkE~ z4%CiDg=d=>?o&E7yJ|{jNr|Xxw)PIChvJ<>Hx2kcA3%v`m7@(m2(f%C+gQ4la4f`U zn;TCA+W#0PyC~T@{AtsG81yznzX!CdO6-88ru7JHufHvXVL#p3jr}u2H&E31m{j8( z^7^MfNjDlEGzM{A3DtjlDZRKGic99pK6E`Bn-ULsgd83>HL>wuW@%pUW33gdQdu&q zGa99xpERQPALEhkHxu8V05lw`-xHpT)CARD zT{?2xAkxu%6e68Je1t&ZL5iU^s=)C3@ms=cAn>zNrNn5=DNH-{YOxqc6r)poSLfGDOO8IpD@;iaEr z9_qDQbDg~QBPoRaa*S_bgSQeHIB?z*fKBGao)AEJpUw4VeBUD!cj+#V_d%5{k*k)I z^TY#!JOI~$uHw*=17`&U-tHAmGFaV49MtAe?(ctDdKAgsj{!UUBlo{@Mrt>C_pMS6 z*MyRBcm&W&+G+q1qFgoMe^+STTA4yQ(5^TLcW_u?Cz@C@l6ir-eNHPBfi zYlXax4uALfn0|%vwjU5@L6}Tas_Llh_|ZF9jq<)4MNM{wEg|KKXd_AeU zfXJ)8b%r&uO~?Hifx!cXAGLUL#GoD&g0&*D8mo!AIKZ15oXc@Ck!|2ze$v5%fRoj~#0&YR?d z^{ZE47SRW44DZ47>pm`Z;ye>~V$~Y#CB@a~6CW;%+5{6!ak6m!A;SksWS~SGTh(aX z1{dLrpA?-O)X`zxz&LAel#cO$^PbAPZOV*=K9(d~H~aKj$R2d<(I1u0C1l;jEuAB! zaNz(C?N`z)xd4T*noHE&vJCN+Ct`|8Zcgm6(x`KIYMDXmGlbCl;QaI`A^l09(QoDt z=Z!85?bIk4u=P;>MD2~OqbP}~X)?2!^aJqdJbY>i%`~)|^L^b4TELNWUj&-A-JR}X zMTiR#?;gt|Xb2_;4cE)}ZI3h+;goir8QbJZ1$EpnAdQ0Qr{5QFgmkRqHZ&E!+dm{m z(mi?8qU2{HS(7(M66NJFJlL`ImBjPfE2vuS=6tcV!j*cL?03&`g@ej&QjxlZSTW^Q zgCs%j%|m5`9kW#Z9C=iZc>i!V1n1`4CCpeVu#7*O$Qak8r@a&_7c4f^?yB@uDKt?$PSzQ$3|;K8slUdnLrl_v}r2 zL+^OCH7f-kkBSY==7*-iPD}mHRPZRn528=4-)Wng)|&9Fkd%J-^eo;K^0af}q14%S zze0AC4RK(LLHp^+L$6U@$(Zg2vdb2$w#FxVLhG2Xb8w`SD$Xg6_BJV7-Op4a`Mqr_ z)gJi3VwBe#gLqN^4L)pb9!q{8hy{K6_>;%&s$On~d{MtgAn)AG`zHxHEB2r;+xSs= zWb5ur@#uADtn8(9Fu-D*sWuqB+bV-JD_T0-@_1iF!AJE8=aX_qs9`7;YwXWKf?+kP3Un(BA zUi@=$g;}FX_fs>cl*mm0uF!|Q_Y(roENlTQ@NsIYa@W1I0*GCpcYpZjNyfmBA;Cd@ zR%xK-UWZ2ypCPTlOyyUXS+dqW`;tdH!#QsATT4eV#}SyI24YVsVmsn++c&xxRVNb$ zWQhGL-2I+(Gr`7$tE=4y6Kd`Z-hIA&`qdV1#ww3`<5JrC?k%ggY?95A{RrZt;oKx3 z#?WaaoZaI}xkdIn3{~cwcKMQ>Oy!b6PyNg_6_d1cR)4f}4-6&dnzT9WUpLr@9zluG zd!9Qzt98z(e3stOI@0^8x!zJsQR<0RTR2^T0*?Xhjf&M!b;86kx1?7!NGl# zb=wl+bZ&Nx2=ckcr0AS6Vvo;#;EV(hk8-aUl?aRjG}0OIANw)#!((IAhU}Rn_GaHq zgjCQ;)dK>O@xArUi)%N6>#EH|G36`s#?^D%T;0Itq4e-4d#eY*rnidQA-VYJ!QXwK z>OblV#g`WG3BEdwh{7OyfB92`__qb2Eb;g#2E5gdFw8r(9(G;*SCX|I8~G>dd*xLa zdteut_5vS#w_!xHb$o(}^fOD^?OHQbH2uSmfaD|^e%yw;Q3pQ-5dj@S8=#%@Uc3AP zTTSCSMR!{QB$JLuH<)aopDq>g6b_;tnh8j7hhzV&&di){cahNppR+{iR=GK9u z{26%k-R4>NatKAI!=iT{QRjcinBdMDb{AtT@_2Aw68H1ptvs2PK|DG#Md}0|YI)f| zn(mde;(@i-+0Xb*?7!QW|8HXLB+ztR6cBuNYkQ!t zPqEc=Z^2VXN5>5X&_#;AY38l-h)Yw;5yKQNt*lIc|DFa3M&-OG+5;|ES`-*R(lZMQ z>F!QX)q25AIr;d~kB;1GetK?Cywudx44s{ux~``GGg}$SJbseCyGmC~v11q(xbZbB zZvQ+KpD)pQv88$M^|$w|D6sbaF$$i}g96`rX57>i3z-B$N z2tC=J95Ct?|8qtaT%C!Ly6XVQC^r{ZFB(x^03z#a)>C;NeNsad0)1-+u+a4QzDl(z zq3Kx6#DpdlNln0CMHC{WXn@AZ=NxJS@$`MZxG%VHadDF<Mfe;Dt=r5!DM?t`(~B2*&!U_K)=96OWxZdQgaYV-%)t zjsy?*S?<}hXD)iO5d`<}74&N)NDAfRNKsgy5M1t=)-E^hzm{XC8e;V@fBe0Syu)(3 zbeAu?J`e*2s0KhA&1Jf1A?BNwk`xidjHc{KKc`By5~l3k=>A0He?Xdj5a0Pj={$bi#$>pOkr^kurDPsI+D#&RWXroZUymk}mZTc>VsZ%-7;6VDoTDf4Xu z#{S+YUKbS%avq!mR2{%TsH`?E^c7d?T^&VWi2nf7m1|^(QS|GXJ4v1kRia?rPsBLnr0F${uc^ z7+Jd-mN*mw#B)*(;zT4UDA+a4%F0^nviiKn7@s}Y+tNjp@y|fK9dAfW#mtPD5;uG{ znIxV;vSsPj?htqx1*zvW(@_hR^h02%3r{?XK%Jy$FcF;y6ROU^**pAH`+)R`q2&Oo z$^p}zAH%C3`%khO>aS$taLi5mD{IebvI^i@D(}^CUe*K$>phQ@M#Uq%vfH1qvi5;_ z5|3t#fKkFPP^k5a99Wk)@n7zS*{?lz;koj6oGDNG1&vm&v44b3aG#{D90g3mOc7Aa zlQKz8NeP4ToLO{X^XHpuDQf<;QUFR9S#-}lGV2Hon49R-Q;xk~iVR&B_*`CIuE+lP z@%L~2B<bBt`kNE=i!$8%y#^{_vp7$Gy{Oekh=QJn*=2UV{n&EQ+C zbcR?;5_iX7;*N^Jcnna515S%A)2ucGi~T!>;}4jbncqDA9l?fjFYN?FJRy5G58d0c18KvjXL;YUTM1R*Du$KPQlM6>x4dGC&{>AY)0$e1MTa-?J zVnI+zmvB^N77qF<_n#!f5#U3CQCyiD{}XxnkLw%q=+{m$`TvoVlDQMokE%ivaPFo2 zb6QL!Y`^FoUiDYQcoXV$_s7kl{pM8v8nPP&k_itvp!lnSh6+XFrh7(z9=l+fOjKWw zNZS8K&;0y_coDY5|MLux;EK<{qtG)y<(xwPN=sRw`s$WBi~g%24n=#r zg?GGvGPVqp3aYRBIA(u%=_E4wt|4>%!WRFU7Lj`XMrWX?%Rw;R6cuI&GwXPzNo?;{ zSpdQ9f~e*O9riCu{ECiyX^b3t3>owO+Of_g((2p3U1<$frd5Ry_Yd#TDD~gPZ8M?3 zgfUII|4zt_OWci+5EzRy{D=OkButs(7%W2e9(Q5XR>+6{Mz$I1qUJf`TPysF8X<;v zX*W7au$?0dUv}=lY-Rs z6IQEwYc#)lD%1#G!j)f5aQl!)id=IIM0Yv==U=?P7_3im{=uKDH_-m;@mt{yygx~1 z=Za!IUbSJOKO004DAuF9?0BsACpbtZ=GVTsYI^?J&{@Mz;gOXqZOS z-R`~0pn{Ye_J)FdgN&|jqr`2uG|N+Flgf^LNa4P5hBeiQ7JjX@F)D|%y>`Rv8`xZ& zc9fwmq+}e4aJ$?NV|m;z8?&F6(-1G?dgKimu}gyzrfsuCOC%uiHEx!&>eA+ha-j_2LEOHk(01tICEg z)evWxrj7nsC9h{LKmQUR95Cp9NxQ)O?6ry#uqJ>pPP}$myv(}dL_r~Al)j~YjQn%d{v+XKG(&ffYx+EOKn&U*NJ|k z8B}_Gi;81jPan=A-shRzG&g#hUia^?PCE^1C(Pn5UHzuUgeV3l_WCBCK31!IKMv3I z^4>cYHh#1^rKOghQj+VfZ3^$48s*C$H}Jc6qP8>jadS?3Z(RBcyQt9^y;YRmpiNla zGaZnW<5z2q%mqv|Tj_0QC31pWUMuBQq8G_t#($d!ygw{LGN;Sn3 z|HI@sOyj=44$N4(q&$g!TZMkELA`4KshR|;$PfidKFWw>^uW_IF}P*yyyxAX{PNc4 z#zoZ6Tb&wG7sKM|kcCz4^?)j2pZ7XNT-kpB@#OQR9+`%SOSRlgq zWY7mI)(FG;KHSn)d^9wZv9J@Ahxpu!N}0;_x&2ScYp9J9Juz;zPceva{RLoFoLpS# zYirI=PKyfbyh3vTPAcMAVvp9xqd*5G-`{7imT|FO9<3LrAx9b~PWQ=u*{ruxPyy~T zrW^nO}dy%R5k^WDw4!Yo!`91-AR<$)QrAFzL z%kqBA1ZlY@Pl_CFrG~yU;KPon?D@lOY5_xr&8}BLO2F$lPC|U1rSqDvP(*s{zH79x z*cFrzxS-@{^_=Er4?2C#uDB(6ICD`#gDScpN{WgqZOzja^YD!Mmtx`Sy!B`%B(Y-+ z$uP~?M)>a=*eYEj-gE$1H?X|K-A|eMGRM^*BchNwY1ZS9zEG$Zgi7zqz%vz)iWHV) zmux8-Nt|*$ZFC$Cbw0Fr+h2iY*OpcR3>`b-a(dSk$yj)KRgaF3*S~?5(x_(})%f1_ zk6L-oIChzLD{fN_Q=?ZV-?!H*F*NNX^08SrD>7eJyOxBfWwR}DMy)A*wt6EFXit^Q z&3sa~>@G>3`L5Ipc(zCd{a5x*W)dacUevs=du;X^=D4^oSzF;auc8tYWr7PIRsH7S8ScQkPWOk%y}BNXP`;e5P4t+=l?M z4N%w#Y{uXdv0B>5z-iJP;xr`KAjQy?6@omDaZnKp&g-+9=Gw0_-MsU4^_q$uLQ)(~l{>?Zl zgu~JR;Q&Gu|wBIRqq8#);6gI zYi+oVr#ZFQgl(z1#72FS49mL28XBLdL=qEhfA7l)_D}uyy8v>m+%^ZTZsF%HVb)Z8 zY1{)ySLCjEndeY<`E!H(9yPIT$&(AOl9m8)$Lox?2Dgki@QGLZP3BETls5yzA2fa3 z`_v4;%6U5(`;!m26`x2+Dvr{A*J|;KODUnUh6Nb$lx$1-u7|gG?PMPhuP>36%|?ys<>|yiQv6|B{ag2UFM`G%?yuZ8wW||X$rUkO3b>W6 zVGuTZDN~@}m&F4)tkKF{y2Z;%KWupSV^JKL2J64kzG*q*`R}25+w5Z)yG|q*wHQRRHsJK}w8X5BG=KXa-adoA^a~(%V!^ znS791aoetlnz^EM)W5Z#k@EqpkBaFC+gnYV=Gkd>O8%QdMV3s!%KQGd zsyP8Xqn!8r0*VN4v29~#UCSbG9@x;%(1~z#1p39b)j50R_=?iRR?kvFqt|o@1tk0z z!^H@nLcOzv=r(PscBK9Tp7W}ZFtDn83hN@l%;Z6_&L#NeegGgB3;X1B6tZ|kmh%I? z6O}aZASg?Rr(?!(gtw|(tHT_)a$!0dvB}SW|H0&&{ySCvrJD@C5|>V!FbaGIJ6#EQ z*)GQtyH|U&q3$jhAzvM_?tm%Wf%)tg$gAdh$Fl?kJ3(aYH0cE*yTnviJhvpu1kG2{ za%dFJZ(@``RDixN&91>+t1>b+2Z8)FoVElohL#q^yo@Rw0c*g|?}hS0rD{cSQnUF} zz$FuIADT{FULTtKnPpYNy6eOAn}iAX*9K29})a%Q}=#e>WSbMrQtAFS=c~DrKt9DBQDrh z*r9r@^;Z82VVA7cPrwGQpF!g4Qd$4S`+y%SUFb*cSXkxOY;o^sR9tAc821`tPDI0O z2d!fEr(OijL+;sfw^wu`#VYBdwKcFuhwxQ>RWn(EliJ zu`wG@Z?K!5QOR&qO3eQU#Qb`kSlLa=0~gIJ-P!XJmiI(c&NHw4*~m?;c0#Le>wdy+ zU})@~hf=j+{dGj%?EVpbt;4K8eSeKy3KgY-;d3+UbRor0Cz7&A9b{CX%VwPaeM#R` ze2#L%I$Z>OnZKq+9uY)a2WtP6#gAxxk-?6T1a;Lltc>?c**5iNmYpE&Ir25C_0X+- z@CD7=OrsI|>Dt%dB8pX0alz_w4mz()*katIJQXow1joNWOL6v$fj^Md8W=e$8DbiU|>Iku$C;>Jrw}w^c>FHt~-9OnD)A;n-cqKjZ zCP}AOZRT^vUPs%P7wC!C0$KJ!V9;n%6H1OZkB<0GvdZKvAbC{%A!g~DqtkctZh{Km z#Hft4v78~f1za{UF`p+ur^X&P-0k#)NdGVBoV?n~;LS)iX4Ob2ZqW5nr8!dGcjUvg3C4#Eh-&4}Gy zr&&XgxA-pyo~zKNs|O~nhtk|4yL`{{l;x&NVFB~`>fxJqRqv!s#D~%#*$Azl1!xUgaJ!>8VJ_oh7^|3VKoX;#%Gn8!2!J%(Jz(`tstYNDCLDb#cInG3&s5 z+L)2iGUZunxVcf9^+Xevp))gR3t|3YmGjU=&nIo6AUoS9vdooQiu{+9p^$gXls#K-IZa;2@1b*!38?Wbc z3qvdojpy?9`ITA6W5IK0FN;yQ$g9;t!lSKIvg`$x(W=4eOWRg)_)`HzGp*=#-TNP& zEO}IzWps$lt<<#mIdauMK7IQp2KK-JJTtVMewEUmsU~ zmsOp9aF6nSwVMW+o7^x07ch<7uymj9*e#6WoUy~MP<&~8&CX-6W>me9L$YmV&ZvbYL;l7TGTD4WL z6F`oVYVFyCR%uH>D?gRVTcRa$I=sY+XXLH$Hcdkvree&H@Q>Jn>o#_ed*6F%Kk&W!;hTlK+as*uC#8&^4ZHly+#W&BZmX3RhsafjMPUUtoML?aOU5BF5kb zIWQx#*=?}O414B2iCz^7Ihl_09RclSVeg|L_u-3zO>szzTq)6;wAZ5@=2HdsV@^$7 zQP(N!>?q`SGfm>zW%Aw;coIuNWl#D5Fc>VDzdLkjA2zv0wK)w)B$%#TR)ox5n*kOA z^5YO@TVyxkiE>R|ySvF?H%;H#tNo+zrx7G`LdSx0_euzlD-Dsv8F9EmX8@CqHSeta z#kr~=hl1U4=e?Os0%DGZ%R@P&`fzNKw~tJo3UXqb5o|f@m4n4mc?*3`Rqd@$dlS@T z8EYh|Y3osaba>H;m=U+CCrWsyoom#@dtb#H0ZS>i9n_B4@SX@JKkuK6F(!`ca8QrE z#i=_&WEF#jZr+^Fy~D*8wh!}{ebx*;x#goZvBg4zC7DYywqIXa0_JpE3;2a%d(;g& zEDE9iTPx23zn~yPK@-bn;@X{|{75rNQ}ljc?P|U5TdhhMm7`bs%d1Pu?WUK0Ud?@o`X{m}NWq2^ zb((#e$hS0!@3gtT2+q~-GHicu&eQJ^WG&EpR83-kIc@`Y^8O^0Nm4kuWb(sTmBmvf zX_4kdX3A-V1n3HBxroTtLhSQrY^LAjDP#G3*%voRq1*pnGKlZxzhatQ-{lBq+_i65 zeqw#FVxC4wD@^}AxLXR$SCzEDUuqwev1{)G=erKuq`N8j=#X#~aL#BWb7WUjvdIbQ z=`5#Q|2n~b#n>7Fk6t)`@@aOc>q|QMQ6ELnn~=M(L$_osVPBXQl5~&494y~Hchi1@ z9l7yx%zIU%D?7gHRid(&Vv`{0u^ zFl?+5%`a4Z55f#{U%{;u8_lhz)S+qyr!60kf^L6}ryF5zsunMN-IwEf_ zibq33^JDsW38}rGVcY)I(<~@|0Edvx8>(N3@N3!U+haXy@jSm>Dn;KBcmv+!n+{g1 zpT~C-F#nOJ_CS`m&88HRZL#5{cGP|m$j{5`;nCtzCeBh=DqdSaG^5o!%-NZ z_$avDXuMemXw+z`9Lbm?#ln*5Vn?N?wuQnNR@a(@*(BYx(?c%COF|*R!Gd!D5m_x| z&}ayjX;-^(1{KRyRJ)}8=$6oPXF8<2nJDGau=@$}YAUDS29k*nnDdHKp6K6G$cg)L zx29z18)ur}x-;X<+a+$Hk={NriNf+){XBF2)b-Yl8PQ6Ri52|tFo&hm>Vvkfj*_C{ zO0HA6nsNm{#B0kwP_ty?^aNL$3ST33_wma}CV%Fp;Rx(Gq+}W^Uw*Yp#dCDL))5e_ zoV3Rz?7X{RIaRGDgh3fstj~gx-q1EA)Canh>fsaf5sRG24j694c5N70Oz)uL$3A{_ z%{Wyc$=|d{pqj;@7u%xKHcu4MALk|exW&$LSX8Wc^>`0HJQYZ#VC>}o$iT+miAhfl zo3Q)Ed!dO4p|4|s1ADhe_m*cndobXsCI>s&WPt^Bg$wJX7J)TCuiu^XI&t(9Ld4np z=iY(}@2h6+Q1ElC1R#$Yw6et?2*|9KNJ0OVAdor6c)#3H?K9w5V|eMo<6u=>z(BC- zQ4!g>0}1yM((Z(blCkNsY9;?57K~N$ zxc{QaauMklenRuEUe#)(Wjel!f2MMyz$Rc%%MSL^)f3$ZlPA;Chk>E#^@l1H($KMt z%@Oq)qcr=lmR6)fkjhkkB*jQpVns9Q!?Z(-bBgDn?L5-6$a>yOFdP5ENA+`~TJO7W zi;6Zd$$3hG(*y`<^b^wT)~!{K=C#5Yb%my8aF;#X5ExOO(vd*givVR)rjSpBplZ_x z--j{9Bucc<&tH6;K2C>@Q}b7E@E$LcQY^LBtZTl*`zB zrk5kmODjqILuM!hVh9o*q<#n0scj$Z?=^`TQO2g|WBcM)5tz z*vbYxc!4F@_;u`gjd6j=CD{D=7E%8R-u(>wCkil~d!=)UkqTWH(8gv|)xmsz4~>v$ z-cu|SY67-!hTFB1nDyAN-0P^{BL5(!aq5=#f-z+`+tvpR*C}!{xNP1YmR4drUpdX( z%`)~s{N$}Xmg4cSoH7puY+=gm9j^G!J<@Exss4QJhI~Lx~8@%@A}15yNVg>t5BQ* zj~-h+922UG`D7;NDFz&)2JtqSYr)X*?)@2Ab3kguHUdIT!^1&(vnKRrIr7-YZ;$M7 zF4OZUb|dzku0T8qkLbmkn1pCyg-WcnK%-=n>t5uIea^ZYq5sz@1|p#sHcQKRHk!-M zZqHxW#=^5XtS&qpUD)CeuHOdnbK_%RkUG*@uEJ<9ou9_&E6x_M5}xu@dkCSwTdz3S zHSSB4Mzya!h(6{q072rD9aAQAs=xuVn4rw{wV)jvgV;OXjP*=}*i6HG8{TObYQuKEP)cL;t*Ytsnz(wb3?_ zA1(cqhJ2*l)I&WVogrn85k`832KkbL4ksPikvELC+%&EG<4n)(fNwuz$JTa_6p*xZ zaAeos|5sMgP=l#k+RxAhUeUzu_hdq!|LwT7eO!)`vjWxGeuKI{Z5bIL0ALtyS60Xe zV!$UJo9BVsPjq)az4)BXFcTfL!$T011Da+%Ij$?rp?Om?AzL!;RPjUdZR6o(df7+L zzE5jTYBdY^>9ju$zRjBt5mMRzQ1wH-5bd06bk;gvIB%h2DV9c6RQHl7BtpZ(W6_jB zwbT*nO(f}%VlSjU24x!R#R)h~2C^kqszIS5?Y~(D*S$mk(DwvpBQ_w`bm0Vg;k36=EoqMstt(Ri=)tpOWF#$ z!fykEa-c7PgajXopBm^Vp!>aF)@jXvI(|~ixGx3xq@z%wil?s)9hdlU{7x5S1o%1K zGJcEr@#?!!S)By4^?k)0ia7roQ%WJh4V{bHQUNL(s*&WqzFK{0Dn}p*zTI5vTlK|9 zL&!(Ty}f*z`uh1+qt_mf5o+^}y;On)deO7)tPQw?LBLy8AJDvF`Rrum%fOA(k2o_pt|>;2p^PebS$rZ<^$Oc3g+Z?ZXuY?5ZSbNX0NBBKpn-y-3^n zmHX{4wl{xlhGykFaLayO%uVCMS~i#{9!`l+-S#3t`lMW{j>VXp4WF4$m+ z4?r&Mn4pT(HeHq}tZbr3Gf7O98lcG4^vE|GnA}<((Y=0^_bYBmDsKfg!Ga#G<-P+d z>O>d@JffzK6tH$+-w_7^d|sz*o6iX5-DpNDWd4+L4rY|R{b|PE#`S-&_ZCcXWnH*1 z?iL`p1`qD;8az0`J!s?Z1PD%W*Wm8%?(QC38+Z9SGn1M3tGa*SR^6&oU0qFc`mDA0 zlD*_vk$lbiCFA?L6sQwxbS}DF-3v72l$6b1)WFAFpBjh+JA^sR;JBZcr+yOI-z?^cNr0=Cku?^?5ev zScr_kU@Bb~S)XN;@mSGBV~{Klxhj0iEqnWzpyl#@W~@H0a5IK7e* zD1#fvQa{zB)$rss=a-F}&c0Is4t=|+nUCDz{4NKjJLx-Yg;zC z{bK(5EB}Ypg%(c09ZMCXd789|Ds%3eQRG#}=HuFICvGtL31>L&Zju&4J zki(<9q2MOb{6%@qPJI^!kIGvx+Xaf;D%QhYcs+1lH)D}TT*6s!iqQ0Seu152 z+O^?2kGm%CtKKG$!jX$jScYMWJfnFZUf)#4uVq=Zmf;$$>qh#j8h?KgLS3wTkJYx@ zcAJnF4kzMR_sl~Mohr)=OiTUjD#IH3)s{`YU4RVG*$W?UrJd%uCRD9ujPj5zcD@k> znQ}1{eT>+aE3fHEp(s6`yuz^Mq%87z!Cp7eb>tu+W zUNOj)M}Ek2euz?$$4@I(4ur;Qjyl3j{oxPIA-ChxTBS6)KlZ-KCQ0I;y_E)U0sF)b zoYaJ)#9=}} zslBpRP(=f9sIJDs5g;-C9Td!O)+yI)5Js8h=>I@Swp@K^p)aab%6Gdo|NZXU8dcP+ zypshhb6RBtI_)`Khc^B$W$V~k6ZxNF;(hpAkHUN%L7ly}_99)8Yjo;VN{Cc7HAP!V(oa54mM$ffCk1ZN!hzUC&0JE`=RN zL~lwHRi}VjU5FmfG5B{yt}|lgj2cIm5@O4yl1o?*t|KEXoKF!_C8@QerYbZRKkwv~ zooib>wPrOrQj{{S|EUA&><~&tp}y}}4YJh!sreS{f=X`q)UcpFSi%$3Ug~_*OW60c z<1|Kp4r@)Vby%TuRd5?65U<-KS=`~QlG!P!a#ai41zgu-yp7wS)#Qo)HKD6RQ(`Z( zR*3{?+PM1`S;fLd&t%nwmjmj5UnuzE2h%e4$fR6xhYcu4PsL+Zsvw$svIJ~B{TGfCJ-K9ozhsEXoj{ZZyd4Mu(GqM?gCOWgd zTI584$+Bi}UK?L9vq?!{3DcG3vCSMZ=hY^HnEnx~;fQ;YiQqWi{%QkzB-7M7&c)F* zd?8_X@U68)&Bnv6X*~4D&o+MuA3zT9aIoUj>8gypl;8xR>sBP{&LM@1jIj7x2G$(A zYPFaLCEx9?j#9buYhQn_dE%|*muF*o-0cuA$Tp(&jq9}5_Px)VnH?%RHO5USL-)st z9Wm*Tn2qWpZ&-r2TW7X&#q2iN^T+w>6&b-Tyc;*x^$|0yj1D&(*z}17wflbjKTzq} zVedvlSKSyUy4q9hKb_8MQQmNqImY%pu9jH(sK0??I7gN7qHXW!(2S7}19=4=rEfPr zU%{m5^40=$Z?#wip9o(7Vw)X@>?sra9z`(D3;bK4=1aRIN?D}qxC?m>W`;>bT6O$i zpz;dGsyn^qPArb}-OAZd&9xG`x;MU*NXW<*$8l{G$GgB0;1AG&+`dV=_2tn`FSSF8 zNaNhW?L5pU(d2V}hSl(^)#C3&SlrXzn;0-EpW@nj*n0`)A0HVH>uU`+CSH5#URfQv zS4Y#=pU;BUDisrqiEl4o13dDMYCSlt)77nDd_5S5$q3o)^kw1?MWkYdl$iB0juTQgv{v@&OibwM(GaprO-kbLt~epJ zvR_(%>;qrJ*on%t3UxIvICgv8+yTEFd@id7VG)eFx@QZJS_17AG}a+2MsYUO8HjXz z2p(&Niyn9MGG~w2`AbAUoS5vNkKg4t@5HJJ>a?6~IKA37Jq6rUtF>I~y^SXFMDonD zCzTl-$AdZ$cd_?TZ`vQ-1p#8Hnw5Eq>t9-E@2l6b?c5oT5mCm-eAc7SSd8qOE4)_v z$%0U0<GLI6bk`yS|9;w zaSYhu7U@Cj_t!R;lXKhGz+Q_NN%#0?9Z33YlV(cPms1L|-P^>3UsLEe2)y+wk~65H7*&I1CWrs&?t9 zF_^3On)n*2^HV+XwH&`gF0-+Ma&mXWopluFPB}d<*D@>}hznUU?>h^~t1T8Hy8mT% zrW*o`-aO0vcuHt{TDY=HVQtIl)E|6~!JGCHb;>U19A^`g*OWP2TJ|;xHgFu15MAC? zLy(TZjh0mZbX@&z16i;XNp_x(2T!bq2xWrdP4AOROSU=2Zfh4OR0F>ja3!a$MF%B> z3j1vtnu6{k8@h+i)rf-CyfH1s?NeoBCMrH+!r?|}=Nm5vCWC{h^z-apy-o$F3_U^J zTxRR2g3hnNMc^MCFxyrT3O?LZ9=$>*M#|hqJ|L}*RKcFjqYZ>fk_^i*BXQXwJBEpG zwgIZXDx-5T|J7ljXOq}r4q3g5zIIr}YiYEGPW^gtEzF{b{}`-gwf9}pOg8$7U0=Tq zskqjxd;S-~!uGG$E&iQ+<;Rhc|IRj zH#Q63N#1;1qsp$vyY-g2GTpa*&JxWvowfM-;h1OM%n1t@U^?$EuY>ws8n*+C^n+Jo z1na4*W1sgLLbug$&l6U+BhzM@zl_i4QTOb|m!Xz$4%nOyAQ+KXC+CqH52kftkC;O;#KrYGdT@ONLe7CX zjm!duw0ID`8x0#imsh3b>&+{2yDZkR@Bs|PcEw@@{pEF;_ndJvc!iOp7|qf8dU)#j zG916tu!%=7o1r#Iv&7V_%rZ+FMXWMi5V@Hx%vcaCRlvj=>V)p$6H}?T;n-x_Woph> z9xmFCy+yl`vf==}OY&|_<{3ICXc z?kvz64JGCK*G0kxVRs~Qdc2LZe8Vrm?ySa@6>92N{ux-N#TAsR9fSaXfsT?mCmsKB zis=JXXgRS(`|BYs+nXp}SBDTk=A~Bsw`+x&DVJF%y&q=~S!Z>SjzNMd&>gZ5hBV^t zGDz?ZmrO#a7W|*}dNl?ks+nO;ax$~2dz>c~5>1SYCB=SLI~{X0J=F7(ladN!wO{)0 z?26~#8x;gX4uiYUwQ?DTf?F*yL3OsQm(=bL-V7XSuH)UZZ(Sl1`Ui4_oSG>*4g$W zo!t-z^x+%Aya=|p$9x`|a)A#;7WzZeRfH!D*cu-{uPNsBv5P-VU_8oh&g~pR|0gVcHm(!-1HH6I%Xp2QxAr{ z!`>#0UD>jutcOQ&M7kR zI;P*tDYq9%o0pK5YeT;9cRW;3q6o=L`;9L~UG6>gxY%5JNA?E~c}>I|Q+XHllnUrp zDXCTHP+_nU4LU98t{FV)WAGJL!P#VbS14SPH9v1x(7yI~oCJN+`;n$HQC*bTdWQ?N z^FDZhY8M1%u1oL?Kso!LCr0-754INBZ|_t*>h%N3g&_XEK9dUth+rD9(4wDHF&XyS zHoerR?gHLirHDN5KQ}#<^S;D79s*q~!(pI+bSjMBw1{-ekEBB?Jg!yD6xJ4mu7C48@ zZglwwK!wxWivHn~s;_*#jI)tZ?(^kBhw{ROYZGuCDAn3NAi|Uy>2x1m95kF%@9V5K;>D`(99v|J8nk*a0sVLx)kk;f94#vqk zrcRZrA_`LVU68D_+`1MQPa-$fOkMb$6&o(Js`tga)Z93#`IjL?yH#!oxLoe*cv$sp zr&HCHmB~DA&thleFmXAozAoMzQU{4F;$DfMfA{Si;#d?{bkddnhmkswV8{qMQr6ToR+en#I}0T2V=|A?hn6zJwtMnh?Tt5O1}uZp&vn*$7@pnc0Q z^S%`BukQ(=lAxsqR`G)&rT)FVXt;ijT(4mv;UpE29N>{dUolL)|K?c%54gZ-`VpD$ zDHTWp{BYiVFAye`Fiy5^gyN#?p%^&+M`w4YgMRo-+coZQ4K4x!e-VOb6YysGp?7d3 zR}9SPol%U)KO7)OpB_Dgti54<@=SvDcLU52gsoATE^4I@#7D<3;RW2K7G4MD( zI{KNNEsTzVLBY+vwBq02FHuxhHn%jv^+`tNiYRI>c$|Sz?Nq-#`(0siF?uW0ZFNnJ zXiHL2t_awjkAXops2@`D*Y=?XHp6U84EhysN__l#8?5q$zK?nf-LC%{tSp&#n}#Bi zE-ET2Qs(AG+fv7p)Md%Z$^Nj+0+aRjhv5px^JTH8D-9zc(B<9Q8Tl(Lw}VMix3`x& zxy;c_!3_^SHDaEYR*kxV2N=oC`-|;r&j)+ZKq5};pZWR2pf*K+&_m@&Zcnnb_N_l&GtE3Q>c;+f`oBqdc2M9K5E;LaC?I!!Y zZK;(gCORZy0qx%{lr%In))->8KdY;iic3o5+NUyvL$kiL#z8@#``*D}+TbkZBuC|F%vO;)dI~kI!vDoc}^E+=j2S?5GUvXkW=tMoL5)*PfRuI8O2wW(QbVD z+m!o4HFJRDVQN28k&<>%qm3)uHu2m2`sP--R%e;0ueMh`!Vp$m!f(3830SA=2||tq z4M*zHq9fTOIHUAEl)e-Ql-uwg7pjp( z?E!{5GWb6Nalj=S5UNCBP>JYf3KTfiLDOFrp)3)Z5h+0;bMOml^9NM6nFuzJS}p32 zhXZ2H=1=sjU=f^q5HPv1f8CZ6l%1n852y>yRNL{LRB3*`guT7}Xv$ob(SWp43{ZCw zjz>dH%~W>~W5Mu+}KR|DOT5E;}KY!dnKR%MPRWOIA6v_7LzUS&Fl zS2gg?7KNc#GK%Q^i7r@!&37N3S;Rv{s?vCIE7-;nP}k*hstYx7N=l0H-Pv0I4CHb4 zXAXZIEKJNn5Qe>{vmG48hV69D38<^})924W4ka7aR&FD3n7dDirgYoC6Y4MNOW^Z@ zb#8v!{NV>>b4`uGH|0%NA^g;ZxsZ+WTJ3nK)C2zlFOK~@2{@p29o*U7bz_95^6_AP z#2&F>GMxf`f9KB;fyX{9w$N~R9_b8RYgq`l_H1B=J;!BDu#s^VX`+gr@PmYv)q2;V zKbpjx&xdmnjcQtwZnD_k>vkQu8@ekBYTC8i4P|-$-6)%{H|Y>z&UJLpGgfj^M6C z0b)&ovg%d%rQT-kBdCScv^3khsi`TS(C=}rs6Sy(xC@5YHAF)d^A@g_m;grZWm!WX|t+# zpgfqt?=cF5J0rH-VW)b2E!FE-XM$x6Hz^R~p^PHnHhhG7@WovY*pLWcvV}hFZ3}#( zzmMo_6xB0K+pI~2y2AIn=c83CWlEe#=Uw2nNqaCj$+8Mp?kyME@Lll*hm_3(jrSRv z?OKOzGVX!!1 zzEN&S!!2-h)Sqfui`7Zy^tLEYhdUC*G=8qBDjQjoj- zp{#^NaPM^1mLzH+rSXS-S&s9;R$8AoE;d8#t!F(wh)~B|qXStyx}dR>g3UY_)PSxU z1EP(p1lHVz_>b^T+`!f=2$=O+tE^5fVct%dg%cZ1lLwJHiMY; zp%H3c&Hzk^`x!#*`r&*(h>^^hzH8cjRKtnIDZtS~^8oNP8J6-4G>r|s5pGX5&4gX) zew!Kzy%Okp!9Va8acAn)xFWuzhLvW%@8@h8FXHN+@KG2@IQuiRTepAkuWoETFN9crPHr+U{M9M=a0#6zWOao2a zk}&8E*cngf9kZ%Sx2rMlF3dlsVB*@$CSo-|Pw=(tE{ajq}l;ej{IWB@3(@2aE!x zbPL`e)`c%g)J;^-4W_ z!z893-h%^ivHyOY-+;y90g?h^*T@-P(xvoK)eQ+^3;P_SWqNh;1UTV3tn87i(nUL|u1teCI-9zOPw>*{}M( z%#dVIXQJV%;gYLSNpq5!Bmn9bt|$j4Hf_&~zE?Tqdw#4tnlp!RAL;}qG(X5kc-bid zTi2)42DvpzwNW4xS9hU){Jl^phwCQiz#%)@VUk$70hcc+v^~x zp3rmg#vX0CA1R*y6XJr=XqMN#msn)fN5MfERO27K z6vogjrR#CZezggYtxFAt#&;qDYHJ_kC2B0o`HCWTfl5?$?)~|7r%TZBU&wE27js&#r4e+ z+>+j?&=WLb^6iGr!`w*suix}rZ~6&kCC_`xRs+?EN09~tJ$g+F!1*3Me#<`Gk0a8d ze5=i*+{c#(b0^t{% z4cGDeGybhn$e;`%)^=)QBbeRXvjkd9RUBelf>8FOci|e0;He6dcZQO87?{lA*x_c> zHynDi(8HA8*ypLfuK~=%8x+KcS&H3=28|Mj!TM>x)_c7mL?Murn69$`rJdqL64-I5 zyVy65tlt-}Z~4{kXppQxdlkMTKvAtMi@$LIG#nAfQEe8lfyW}@r7_kW|8 z&rKO?Xxo5G?SETym)PXu;!Z@*w!-l?Sgh>8cwKP0=3jo3;rSS~|F2iVlPKi5kF~%r z9gs?AI+o5z?al))&sXL@_Ezb^MdpDV0{qM>8Vim#}do7R|6+peD9bdAtMlN{olbM zSXPEMmHDup!BZ>UwpTqYyQ~7xsFjkM?yzyZ#|7U!i7AEz<$i8J+VyCNK9Lr7XmyBw zt{Emvpl^ilFJ!0Wn&6Favk8LR2SnrJo9W&{HnfXHFw3%K9 zRra|P1bjwt>lQNLkA9x%HX_9YAif>vK6La70=$2ph5ov@nxGD{H@k_Y*IIbAh@{S$ zxIvf-95w|>b^csBmM>S8!)&HH*|v>iEDw4ZV?ft?XOAowS~5i*-mv30Fkpft(?BP9 zjfS%uEK#WuMbezO8(L!&EPBaiOM0;XvFUfAFQfG$OhNwdYq1fk;)PCKV2WzY1Ka?N zKD?&cbWln-OcIbZ*M#watEiofPA*5hvow>O@dLzgaXK&G7}(u+UbDE<>n}S5mgm=S zMM$IQPn1zRyo7nuPa!B<2>UKa6|PR9XYJ-o)vi5W8W_$N=!#x%#dI^NpT|h)R=yA7w3L z6YaV3=M0D{<#N~uYeO5!{R!A*ZxrLL56OT0-z*2X$*j$8+#1>OJR~XqU)p-m{hd2e)i^i&>~90 zjR;(PCTpTvw&d*pU>HrpMdbQH9$r^5Kl^L<*Kc{0RWY|`RI3}&LI@pYvFsuS1p4`l z9gGll#4m)jA$wk-yW%+eXe(+UNOKSLL(z9Q(OJeuA$~JizCg4B7l?LABiWpCKXOGM zXz8f!dim1}VIGh5`~l_yF{S#qMu)wyi7f_E(R7HH2{^~q4y*q*(?Rp^s5YsIdl0ncHVHyu7o*t&+k%eVR4zJUQU3$i1>T4V;4O zLO894eJ)?zMQNNkMW^>DJ54OV=CwZFAwaBeA9wK(NZIav#d7X#&%GLVzhwP$lJ6|~ z9fTlx!mCNsz(;IY780(?BIu#OJiGLp4~NmzUL4AK$ij7|&}I-Dg|n3Pec~g!d|A`i z^SV(b4qTx~{f@e%$$=Aejs{576ic&%#Vyrtnyy7=O@-ToSpXbYN6LK8G|Tj=5736l zMB(%qAzNg>^|Rdc&aXLxcTLrAg4At<)d%ZM>Y-!DloRVfH7S6+oB!rKTOG*Dd1M?f z{HDFBX^@wzX_yM~VXGPy%DT`b7{hCXY#z9x)C(cXnLcKnIWGn1ocV58`6&Dx$BWIb z?U^6q##$|JxGN&mvN0FoHyud3DTH_QBB}T;bm*4$XS;9ClA!rmu(9%#iFJM)t>4NX zr}s_qV(Pi|sX{w8U0HXZi6lZW`dp!Z`RxuIO6C*V=EO#l?@~o1QGNhTK`z@ktQ~c_ z9~6SXBQ9_XZN(dEQgOyk_j>g>XSezg;epC`wC;#W4d#~`x7${;^nGMXF_i>>vU`U)#*U@(OYD1NC;fy zN&+fHl0n50Blmy((F}3WYNI`3pz3mHWUjeSx-~_dAul*JYPG-<;cRXBvhThc>L{e! zT#U2blA@15tWIzGVOU{kB#g!Aw4=_0v|g8rJ(* zDu5&8d8@rct;K|S>XiJjwHLJuR)}FbSrrzNsvj}|I!)-i-qY?nk9H64a>CTV3CWH~f4`)%7eZN}c+#)pcaoV1&X?;Cls$HQ<1`Mi0 zAuuq|y7;@@`vY&Q*u`D2e&z(!E_~=9Mpx=i)-L+V++Bh*V6Du>JK}05e_^WV&)^;J zHlcE39keCCaP?Cowc><*7yRX%ssH@A@$@5M<$A8iin&@TCD}b^6Qi|D z6kn?m!BQEW=+I0u$Lh0zzTW^GROl%v7&Lm{=Mrw@YUc|JHR63@mCv2!bCM+f#mZ~H zB3#T}VbLCw0?U6aM{jH~2s}UzoI6Ks@XVBC$Pl)JW zuU_gdv0eOOCg4<-$#Jm(gp$A6+6(Vyl-BxkyJ9-JeTO#8+W&f7(P7gcbJJ}BK=Gy(PnRFP#bc1q}_u3YgbavvS%!~by9+fGo`@^c z=hZEDQ#d3*$=@E$6Ghry9fPR{2|vz!g<~|7bPvk3{r6y5B&H<0$T}e!80B6<(18JU zZ1Fu<&53i1B%g7n)4Znjyk4+YgZWH;a#r})<1ohduclDU0ikx_d9LfNZuuL}?=SU7 z!pMDG*E$>h*$*ri%GrklPVp_Rx-@#xA$+4 zcfAD~&})SRr#L>DsHm2$|0~13q{TK=vT0N<5j2^7T&^C0NJC?t+M08Pjivn~~% zj?`E$*w64N|15v80!rF7RXpU`T>*15K10wJY83>mkuaqc&j@+RP@Dj_lB% zhYzK={N@j{JO8nfgPthHK%;+rn&A%?fUo7pILe!X5(qNmv}CzfYJ?SNDt76 zxYT;#kOu1jW*8#K?fwYXb^NOG;4$Kr5rcHDa0HDFn*~ac8+#0V$JjGIzij!zO;U3| z-6f;+OWklBbO6RM2w<60;zJy62q-gp1a1Q1fjGimwl2hN1Q2G_xPd8wuuyhyCSBKJ|BLz4dL%mz`iYkZ zODol?Ywx8%-+dRrSLfDuL;M;Mr;};tHuXSlKxp7x%fB@XiA--*%a1(4h($4(kZ=Gf zh-7zOyp-FrrBAobN#uWF@aEzer_i`>m$~f%b%)wd9iF-gPX>cz^hzYOmC*AiFz*ZH zj^)RdP8zmmy2l@;s!`SjNotyRQF)Lb4Lyvx=C4UZO=x4&(ujhZ#$>U%g*&Y5@{X4m zktmxfMD?i?Zx|WpR~J7T@N0aOKu?k{1ZJ2H<%coi7f2#S24)*kTrHd$MWhvFl%6&! z|1H2(y;GEv9*i=T8D2O$j<#Y&xuKZt{KP|34N$q#?Wm|A{0;`wlDZ+C!g=-EBQN2| zqqsY(XfU`*QPTcx674)(>9jXzvscx?0Z837xhyNg{*n?n z4VOJ6j>o#(_K0tCKOb^^x^KpPKWzN?=Aqyi$2dN~0@NP{QX}`L_z;9fmUCSAkdWN#bS$-RaO-wTV0Oy<~McJ)D zFjQKo549_shPZHslTh1-_Muy0<_=Xzuzn;};VAyzepC?Q@ZV>Q0z^K@N3B7y<-a%F z`!@`@76b|duH~0#eEw~W57wd3qTj8=E_cS&v)clLb3(xqs=m`2j%<18L!1+IO~an_ zLyG#prvt$sN|BuZ7x0=8A@c(6-R><(A+I0MH0VqK5 z>(7TVx3GyZ_4+JD!oZ;W>n0v;VgM-;<{t?>7=rqhqUvrBxy13;Cw`0XIy<6+^4;;! z4TBrC_K|u-3_W9d`}&-YohvW@6{|C-#+|No#Hg6RD^7%c`@fNpq<4SXtnz0TA^juO z2g$!hI{9T-?YBq^jl%0ELnd1^$}`oxB2x_vF=M9R2Tl4nKKP-z0cU zbhsd}0cobVq@aHeYt6(UId9g>tm^;$9Fr7qlf2n7j-m~PP@rD$14^}+f4(O|3DPoy zgRXxv@Bgd2qCu*Q0P1@il0qv1iCiG@Y? zf7IN6ca4^Unj$;jr)c?EUH^HUSeaxdct@PkXm6GR?qsb+;q|7s!{i{k%l=9(^90?= zkV1-t079$YCU!r==W~AqAsJ$M)5kPASLFYndV=G}%;AF5U9}a<(DqPt##EDFRyUn{ z568yIIilcwE93UKv~RLlX`quWT`Ee2F7yVZS))_Ed7rLfaT1EhZvU-Rqwb6MYna}U z8asodNfDqlzBD#dyJ5ZOcB!D0p{G*tf}?~#f1cLQ>T>Pr_<{3Qcwy}1q$KK% z`(b|jiG_A^BooxvZSat&s4_2H3BR8AExTX)1h~Jr32B-p2@u4wO2h1jqiEcvQ{e9; z%lSk<*Lq(DE(szgMN;u3f`wapI6VsoeSI?_-*>cu*1-G2PoYFmjfP0#L6C9*ddY3# zFd6OL$n5LVT7Q$%Bqkk4EZ?HKc;28g%21qNz^4c$s^6TOfY%UO%(UY_+e`9 z*ye1!uEOopdoxXy`-Fq5gFpQVcEph{qmVZKdPjCh0og}eQfcki5!vO*o?r@{P0BMe zu5f?|IhPy#Kjb=Ufo!4UO1V)VZ&>FFkS-=BMrmkdB%W2iz(vH&PLi9^`k|$iyLu6m zo6W2>oIZ(0(}Ii3)3Cvc@eA!h3Cdvq_Q=o1$0SeZJydcU(!K)s5!7}HAka%V|2h>k ziS6EhqDiq`o9~ixNbZzE)M4OA*2Q1n$?u3rv$Y1RF7SQI9v-k$#*JA`9oRHb=rTDSxvC7#be!P@43>M^jDLk5?AlKm* zXg{h3V-HQgR1E$UaM(SvbIFLi9pLTP79k*}ke8;aRQ#jcAfWCsC!u-#R1cP+GTd*u zmAk?ix%AM{yOmd)oe^71PwNTvw%930iJ!QW`OiH8;sw{Kw29%baUquHgDHB2v@h~* z9(ObLhlN_L<~a|foMl1`L{1KDHQ~~_^U-K$_JJb|7dV*nWm=3YE+=tQxe^k2x*V~0 zw*o+R$~1v{dv3t}4PGPFcm@X$#J*ux{8wsm_Tb&2n~p?Y)8}C07T45!?OsNzbRli+ zV|3j8{a9UQwSVs9Ei+hng7!q>4E4S(i(E*4QvC?6x- zbZ9?bs9UXn1olbxt5cggY0k;mbA(d$B9mllmo= zTJ>f*hTXZF%hlzc%hz%dZVffExtj5|HpJsz)1;{_P9@jJC)aHg_LFCTozOUY0 zgcqJ{&UQOw(Hwb;)6L9vavpZc+yK=YYAKnZ02zv7D){QgQ+M_kWK|j*^-S8bt3GAu zdMVBm(#4J~qpE%xuxqO^_Uw>ta+}v5x}}9oo?~YlYRFj8zkInB&t;zwb934@(5$LZ zQ6r>_N0huvcx&`*ZCH&Iz{J8DTCO{mt6r)xbBb#ndyoqr*<}O*nXN_f5owQh>LMhK z>lj`%3ijPi$np0YCU8IIKAF}xtrLNTHPnNKbaD{Jd+`v3#reFIs?3-z$U6|nzS3RR zm155mO*4P~h#wg@^wXQ$zWd@~1+oGI#9{6re_ zXlnob(1Wf@(YC=ZI4e>8k?Y{(bN}^F9BzQaZu21|g#g33tIOW@v(NwH1k*sY# zE~vhE52Z;23+Sd+Po(#rHNd}SwEUX8-NbaUJ@`ul2xMDYSlAClB?6yaj=3WB)Gj40 zDg%oukJ)0K{d_d7PRRnVSJo=qF8(D5;!DQFE2MOO>CPdD-d1iTKqpwpFw6zXV&_`z zfQQ{!?q8+P6Cl*ULEU-kc5$|E9Na9hz`1~{`^m02>n7#nK9XJ*!oqnpu1MAEDKGEN z19Gre`C3sZ69~givCFN;eMq4qgL){$`n`w8)N%3s%YbF-srps>kz(@ZP5sALpJux+ z_|RolMVj8vN2YGp$IO|>C`HT=6}wL|JDTil&ky;B)|j_16m!k;O&V9>iLi;M@q+Yg zr?HZ`AD`7Y3jJT_%ob$abOQK|*Bc1bw|(1nl>;x2_aoyJMs4*bT1DPZ6I-rCs?0xX z>#3ZYZ(JRtj-WE)Gnz%5?DBVr9G}slW`5SARZN=GTl0<&$YZ}GW(36CNRG4(oP#fH z-aPK*UT%+24aNz#`*lvrrvlf1Sv>TmYB}9D*Ja#T*usg=m)+q|*^d4E)CJpCV-lz8 zv7DTqR`~e{f2TyDBHp^VPzyYGji(%|=wjakJMsrD)m=kDE3hyA=JGA$%eDid{4bu? z^%Wg*?5IQfH@97}%qBf5#JHD%KHgn=_83h!AB7*Ab@qD6&nHLl)p8LWdXINsGQF1_ zpTBL^ef7xZb6k;S$E2>>F5&wse2(`R6HXlLEPc0!hNNX@(dsJM_C8YeWC6?Hj_xI6ug1$?)hz$5sCafK2;(u=$$j8j_2D8ln*bR*f3H*8^KpxHBr z#LHKk>oRr^=k;DMiU+{gJnAa1pY9>tFH|FIblZ8w=A@rHd?Xrnb7vAjz_4L*#6sue zFMGf*gPh!BJhpXb9L9i{H2K7))6Be}#Uaq!Fp93F0G$~t?48VK=TGW$=u6Ww!)mHY(taB^ox&&Rc^+{vv0_X z-O_zNiiPhO z9fq&{qpySU*Kv*1(bk^rZPz|w?sa>>$xPPw39IW~W}K|MPFzujt4~pk9wYU`rn`a9 zw8z6gUG_+jjd^4v9I-!1i&&&y%iOh>b|ib4%y%OG%*@wv+3{K`<4q%=*(kdkQ(acr zPq9qXg=eF#?Hc^!!rBg_eJvq$jLq*!I=_2==Yb4gzsy8u#qhj{gDX%XJS@Wg@%cPn zuK%m=GlMF{ssDwSiN14j>D1CG1#jpM*$t7aLVRT={ptt7)^44yXQ4L8EFmAmVX))^ z)?Y6wKX`Irz(?yD)uOF!;%zqsbneXjTp&g0>g?#_xdrmztF%amqNmg7)b<*;Qx*@*{Z zvCv#;2P^%Mc!N=kxIET46OV%E(Y9h7Enx_t`jE!LB-wvEb~)rT@&n^?w_u?#hXgO1 z|C4}6zhZLMLS~_L9I6V9ZtY8>gl$FaQ{483O&UXP?Q8T~lXvJ>_MIYCSXq3@l7{{} z1{*I8c^B$pRi_C1h3yhYFVFOypX9^XdnlYvpOhxT$0Ub$6^7wq5*P(*)H0g39aUBM zty!VDU!Ny_5f&@X55M1j91bUK^2dEd3ZClz!L~VYLk|-u;Pog4NFPF0KT1j2@t6Qa z+pC`VWStT%P|4t74#JqcbWZat2vsMVIQ*XL5s(C8oV` z(-J8M=B{?~ZX|d5;Su2&o8!Zbwpz zsYa|sVOvADb``VAc9Uw+xB?hHE9-~%sba?b@cDpJo&bP^aLj3wKuK7z#gKVkfsfP{ zJu|zxO}x@ANZ+2BE%QMi#}{-0YX0~D2Xzl>?)VfRU}t`6hYt#5dcw?cL+bzJ3 z&foOvqO_o5eOd3*iCaaeR+PP^7O@t6g6#wOqPCz?BK^2~d6NG&<8j^CrUG1>-;4p} zutxQ%-A#@Ilx8%x##&12Cr^U>7D<#J)ABm>TwD`FPL#igbzmY%CRh&HQhqZF@o;q#Sa`$)RbJ+=5{tc4Ufsy&tc$*JZMC zj8c0xTHACoG#nIlr!=4OO$%ApH`KTKp=Iu{Mxq!9sS@Q*_S=X?koS;AVk-n|)<+Qp z+aG;b`2md!?+I8-WNJ^IXUUT}i-peGde!Z4XBcJdl`wYqfmWOd>uo$WryN>HeZcE3 zx63f-*kw9WA(MonDl+l+S9GeIK2BrC72Qz|0Vd^0>CX-T=DfkRjBU@)iC? zadVHO6;0#QX43r8hiC%7GDCn|A(U9Jtfs}JS{51QRig4ur*$Me`0&MH#|Myfv|Sg# z%qtf`>|(y6FXkbNjFTvPV41qU#Tz&BJ{VLrF7&2-qi26{pyg=UYv-O`(S49G<%H2e zjvV21*=}>w_-k^7rCq;Xdm3G@ORlM`m@$@W{`Je_PgIsrYi|j`3WF|spEsj9JE(;BuvIG|wOLIFOR3hPFHns}6-4j=QCQ|!E6vsOK zR(tF+ns7Hku;-2fTXOVq=fbIDikWF>G-JOc7#yd9?>ch)oRK9I_((QlY~R7!=0-xj z6MO7qgaiq9O7M<>#N9!9nq*6 z(IYxH`L3dWR$$MH{DGKy!=S!LOrj7!;Vi2HRrQ1!=AuqAVX)ZJ=x!dznQL=TXg9}1oNfW%p*wa?>JO+}Zcvilt6237?`@0*ZvF^CPq$iW&hG^Q0 z@w==~TPsf4^p@WLG8eQolI^+ynlsHHv@xPR8M=;hefl)42n?Cuu-a!ymFg!R&iOZ{ zh7~nH+c6*GK7p&7urEO~N%}K8`BWoo?q}XN=x)OC2Q3ps3|xDR z>LtQd=tdBiw2XIjO@m`MI$yT*)R;B|D(`)1RrCru<~;o%hnMY=T^GX_7oORJ~FQA2q5!5H-* zYF$Kp@qs*3`S~rntNiGK2_}_=j1%Rfk*3SF7jZ!M#jt2GCIiP%#b@y;bE`qwA?64E zx-C>wY{b-pw-%iveg5~)6R=nOoSX}(pqW5?A7KJxQs$SQ)36jU0Hg-qzJ7)xnMaz*B0o`9rPS~gkO8Bx`q{CSeu6B(C%C`HA6h|iMQD6^ZxNr~>&U`et z0i{S^6~8J0zO|UXY9z+ieVnO>*xKKq1Dv>a8?#dS1ZkJRFj*4d#j=di^>uO-$~cDf z1jFhkg22cqX?TLHD~D^v6v9)<*}EI9@k8>EM{e6pFZGyS5iMMkY)Y)cbu%-(E1s?U zUMSJ_?AK!E=-Z(a3|DjhzxKYeE3Rf~JGcdR2tG&%3=ljx!6mpeXn+vh-2w!HyIX?0 z+h8GB@Bo9myEC}FlXKg-&rf*QGoNPF+PimmwN~|2R~c|W4g#&EPRGFtLC8q*!G8sk z+3(@*G$02fgC^!;>$W>r{8$AMd5XnRI#uC#^Pg|$*gx&P87&iNZ$UFRLqOA?EPpX& z6grh-6kUIn6+blx+5|uUp@_VH79osP3D?L)K{05PD#kYHa`JB071D)LyGa~%cqq7e zPTHFwicFXt1T?(-P$fk|OKlPPT)+1@x2Gr$qfvIRoINL#!g+Y55fJq>nwx231Mz6W zsJ44NM)b8draU{7kwOqNKkEaMEjLur#>9!b0}YtP#g~=5w8zRJE`+y`7Y&RIp!Q?Q zu7;Duts;1>5a@yR%D#hW+X8c#6FGRXCjgUDW}5+nVWAxT7az#{A|nCvV&WQ05*)Oq zc>ZH(Kjq%i{7@(YI~Lv5!M*|mo4dp5v*EgD|3ZMYbieyUyIL>Wz%(3m54j!@@GAP@X>?(LPWMddNda!QiK z+1Zz3R4E&wl+^sTGJ&{JI46r!ULOVJd})S5N1@83Q~&!5#^XpS84UBWfi^x>@Z;iyqI&Ty(XRkI`|DCqxW|`Xi>Y zO2IK51iY^#({n8)hKILLDy>HG(fDe*CW<2!I+UQ<6~Ot#C+%R{5|UB}ckAgl=q{QG z!{^7mutN*eDcp_P_u1NV!Q0V&A&t{S3RXAjU^do6*XjpirnqZQd+_cZyk5&+;Wj`Z zGT?j!Y6VxdwH`L}X)N3}bu(3M2YMWr57I9n!lBTdsN08evqu0^h)#S56!%$uI77%b zCp^j@GJfG%ir@tU`#2huGEPV^Z5~(K85!J5|aZ3ALfJD%i3J8A-`!4dUVx;qe97Us?8QnnG4{kL)x# zUpsK0rpn}_I9Q)^^}JJanGuvRk}tiMiBp;OK{XujFuodgxgMNO{hc~5mmcm0tiE0a zys^jEvuK$Q)Juzsnw)O*6ag@Rr|WYC??<=uchAa*#9}%x*F4C$H&@Ed+)wm^}pR={_d>Tb#HK2a%JG`<#V=EE<2pm-jRAI?$ z8i;?o^AZ#zoqvTOmHj$WZT!`+8!w?n1Y+ZUrs>FT`ASk!-`_qoPvGw(J4vR<XH@uC?(#u;TXOpw*5B~H~0wj=lsIm)e+s>5(MqV@WE&OO z_V6h-qDvq?l}o-dgT}fICq-#{Em3rnA*7|x^HPZ$V**IgQr`g2oL?p}YD(ldA5yTr zvdWx{{>+FqFrXM92G{XkaZgc=fG`mL3{#^jVl|e#BgRzYP7fH#>k>GPn#B7(9=?VD zHy{?f5>v(mr8mreUt_t3{H?28J8*hurlq7fkYh&^+r95Sz$58XPoLYoG+JZ9>EBoQ zqNs@AL$&YxUBoFeGXZOW?*ed^pAsLzpM}Ig7*)?#V@BdepI`o9%GYb!E#hFv!FqB! zBuFh6V7Qj|aM=jEf7%_vh~fOaF<4odnTHL@3Vj@@A+ogvC9Mhy^Nr>{r~E~aTn%%e zXX(f={aSY(lxtZuD;wBnGHhvI=vCce@~ImYxfnArRoE#t;CyN_E3l27{diqtM!3(D z$@mtz@q#dEJ%f9EeQJ3YDx)m9WwO`?hm3@3p3@R8Mq_9Z6s^9K^p!iy9U)+5cGkS{ z+yc8p_asbWKo>rm7F%G6t{;2)M<9!IqK-SGwQ##Q!iRUe?DEz<+G@u-j|O^5X0GST4c;BroM57_ZrLHcOe(3SCyJ|ViGZ2j3B@1n zoiLh6B43a7849htjr|Ps_~(QR3md5Kw;fM;B!lsm)*kWBck(CmtZ+7jcJb$-X;zv0 zeHc`@A}?8JWMtdNLRBh%Lu~~i6wCoFl>1-h8XcgF%j-ns|;qN*Yb?I~?g(S3PyiBh?^f9HFjXLyz0(o|PhC z^~Oi*h7c7ODU-$LsNX`eU;gEmQa+96sybSyws2V6QsdFkQj(uI3-`lI}8Iox%p>w~?O zz0YgZ6MEL!bwcHD2B;&V#ytED2={j(u|h8j7<#;@Ao2+A0^VhMa20$rd+;`ceRr)Y zZCq>Z(qFtq8)uw3iHy>J9=F$Zo_KgX#PZDJ6qL*hzt>XE{M6t>*z(!#}Ef1GxtIVux9>!3oE(-Bs8 zs8opwoRY|MIqmRW+JWCK95ff*R0?;y&c5`0npguBRJKDGkZTX~t|SDg&L(b)PWNLD z*p?Znj{Mp(6Ta=Qi@e^()vh+2V$ZJQv0pev-#)yB-?h*bFFoTZ^2sW!Pf~YG$JCay=+A;xTKy6R?JKPK7;!uC|zVN zz^GU*&{pd<)^>h}A@t^?gUSc=cs<6uDUn&}Fd4Nk4*ltX-=etD@Qu6Is*iQJ6Tii5 z?5L0%t6$!>F!0T1cLI6}_Zh@QT>QUrO|W~|#km|Dn?0=^*N}BjuPIu;yI|;988VXK zSdGhC=Qx>%m?_4+9PHZPc<;!kx9Yw~!+7o4D8jJ=l=`}dd>*m(UK3~WDSgy7CXy@x zTb}kuV#J07sm4m`@IyEmBGEAuWR@eE_7jLIYvOY0?o6tdyFiaLboC_PgKoGuF=Sw4 zP^p5j>@)-p@iQU`-I1SJybd@(B0Gh@N|6V_Np+Y55p>@-F60O?3;D#BB{Y6;X0IIh z;B$0334e^aKl*GP?sgTW(l$x4Pw7L%7f1>)Jms}VT(O;^V*SBPbE%@2iI0)vV3WJ) zyu;1a00KN4KB_y5){^1l64<7Fnr*-DsC zL8Uo%Kc=ptgm-|>o6_ex;3q zHUa%=t-v!ehX%U-)QSF^2%`umWCLq-Khtf~vmaY1@AX#6pwH$?;rK*iIx4SYkIbvJ zZq1%!Xm^URJ+%u~tqI>`n=Pa6Y~q}(CE@SuJx7n%>-Ci04HU}GTcX{@YU>3o!&1pm zs*fTJ{S?TrZWf!O()qad0>Y&!R|$E1?eyJa1c2+)fXqOWKk#A@!>BBP_TjX%QAzHx zAFbHYb}+6r|IR=qaNO!vVDE<2R-JAv;EdwzY|1YMj5$JC3WqPW#L`eR`;t;AjxO=e z%SGEhW`YFY(^OMHa~b!MV-5o_X&?_viF8?=KU{|1wzZ7#({v+SR;StO_YIBmxeMOq9PTuCgg{^;T8cYNZwQ}{1`~^opn6UH$9k6X^p1h)l^lRKtv9Pyl3y?L7F zk4UO{#wjjO{m0c|`*nz&jHjxmj9Fdsbt`UmOo-N#`oMnJ2KHdbOP_I+{bQNWsr7v+ z*BjkWj7r5nC=Q~qAI&7=o)Ua5NRQ*VrHKXwydKMuqlojUO{-q>=joAnJs%)Jn2xY( zaq15hjP%Q0C!@rQuDENC+V>_^V}A=AbEnk=LaH@XeTKSYuD465$a5vk9VULaP@(hN2&pEbEy; zXs-=P1H^3S`fD+Mpt_AV(`{a16#NWY(kW@}D~{9K=VmZM3C$kPrd|erh_D?DRiSL9 zeqdzuldK?hYuw1c#Fgk3aW@H>rFB%=WiVBcQ5w>u-_vY%n!=uUXUqXeoOd`3@FF3H zxP$QEdTIoJxSV%3=By{!gF37)%FlLpulfZuhp7@p6bqmNeRVfS6TT(r=6bmq!`xbp zFM>?aNOKPNOM8=)&1ORe^BXFrNQQy!Ki6^bK2lQTXHOkl-wX{=!S0mD=1{(Tv@VHR z%qOp7Ya}-nmlOXyMBX5Jlm*QOBfPyZ;ma{VaM4*{RqM!q5Lr;iZxMpsC|5`g3x8C& z4hyQmkI@sL>!%W9tR!)2VIjFf+RfyV*_&M7iixr#!G{rGZ~0?v)N&ptA0#vkDmy}o zT)VoxBCf(L^ojTJUN1NC7&c3fF08|En= z^qb_2M+(zA{LRSf&RNcr z=Nyj{)T>?dZbruS_B}U@*s~+~ERziLXiWafu<|b9 zByn_#h}=DFA1|9F70w)ci`1ifZp8?1)T%l z84-d}0z6$Xm;YwrBESnp4hRHGuEYtk?b#B&YEwCnWqXdMc9)euk6}>SNssYOC4o13 zEe?<0^`L2Eds{YpX|=~t)Lj2;MREXJ3@5Zeg(Y+?CFrlv%N+dQpkK5Y9mL=8L}!U- za2SKmsc#dHKE>qDKQk|+1^aCToWEh_jXURJk`OeyB+B{7AtcQ4SKK)WE1GaoX>0a-e}~M>!W>@;|IHdvshQ z<=&(b+X_q@5vbaSh^pe>3R#h(t|%5ub1s(BN^VN1t1#%HH0*FE%l7o9stx!=-Cc(#Z>BIYnTWb{X{bgX*Y^62ff0TnB(A2~yD<=~x#p3tDHeqY4;N8pQU}qb6 zb^r`hErbtt6{&Xpqdowfm$1*!(*OK3rZHkIg&K5jD5r12>=pW#?qL{1YGfFOn+91q zmHtn3=-&oE?9YWW3@LhXL1}*XckTcA1AFs>awwd-x$Hj%?VsNkg%|qGHYU^-GAsO- z|M9~mw^HWT0jAV_xEu`w}>+RZTBc-ur_mGn1y*mO_hSO7fLPh0D)F1DRYgx^X-27-A z+HSjxsLlV&P6y!pjxG5_t#Llyk?*=W-tbaw98kUdO!h!PbS)$*ChyC{e1RqZxV{0y zX2*^3_wx~aQViSJ?&8|E5a!42!f|cyp}WO98etW@+spXwfVcFUt%Cp{-GtYGFDy=K zOz1~#E&bQgXR=uiV8FW+6Sh+iZ0!am=GcVYLixQ(-dhT&x6MMkPKlw9<{tJTv1QSD z!58_#7_M@+f!1(|xVY9n1fLJgzy$mO@jThrA})=92(oDgODHF{{Nk;KO;n>B^*VSS z;BfXl9>C7F{9?@s1F&Cu<$;ZSV0h4#wXBEdoUxL~Z`Gaf^Ee+pBBs}b66u8=eTtf=Xt7eSRiD{7_SCc-xA2X$L@$JnKn!)vvdLgX=px9 z7B9EU?zvefB}{CE!LX~`71cvbU!SODTQ)uxdqORX4X(fCEqhzAgqtq?cZZ7Mz&aFF zX1IQG-1(dSVg>g`&;(RBda@Y9cJcEhL-NL{8sPAD9p5F+UHaUwR`(^ z-{JvM#ChAq1Ei5nTi4U?NQVY7Z!4PhsCL-IL%i?X-!C~P1ENxQoXQ)IPD>*A32K@O z%q{s;m@!eVWDobS>CN_7WVPr)Yd&2cXKDmWoSZJoNGjT26Z< zXxcrS#2}`3LLYe=xBt+Zr*_)h~if4tJ) z&wL2ByG=Sw8@Mt$oUhzdSUcY`x(z<3*RkkY$I}hbUth{py@3SIeGXJTy;_#vO738E z*qeGG6OoKc@X#$$ticv^0oKLM?01#BEj&`~`Ux6&JKp5in6Urc*V{E~`29$B-B`v<3;DPFBq$oMXfx zii(a}Iaf-x?J3>rf^zTOH)N#+-uh!8WI6Hy29_^uHwFD;lK|kBcXudfyJxtWfvljl zkm#iMncRbqThRc^pE8}#-8P+`!a!d~GUDUtjenx{EAw7S_}EpH#mqGtx)yx6a?*FL zNX_hy;Lp3w)Pl0VAMUs?{7NNlx;rHr80$=lOcJdS|eQf86AZ8D`${qZ&HmW z=KJ+8_xn&lBqgI|VJ7`IN?ho^CbHa;OH?U5!LnX*zC!9t((Jo5V>r9$Il^O%q)*Ck zsB;WhEvFY2dP$}_H3Sy}(N=ur?z#)q?d01a*XHV5i1O3E-x<3rX##_m3??@!*h>XZsUPbky&E8B5S!vs^L_k z`{t>hPn9xsAcC^9ytkU+YTup+A@-Jf@6ouJ8UXvZ_1DrGe0x-#1SJzg`7n2ws9Ndj zsn`%Ks&knlNaU8VFF}BMEQ(+jq$N1^ zYk*REz5|2#E%3&HV9I$TChEq_98FP8BOg!_^6nc@c9$z(DLDyJc`e!&?D~NMOUB!= zru%A_@nzv?{Iyuu3vQdcYMo@?6W8$O;`qlu3ty}1VSDPb1*qUo>&H9uhydtcr{D&60DD8 zx-6$A8w+9eP$PYT!!q6Zx;k%conFVU@4hYSfZO|T1{~N~7e-?W+p0~nsrTGVgs)A9 z-7=XmGtHHM@pNA?v$I+@>5&pu0{O@UrmL>^Sn{VJ(@)NZY43hibVoWbScNZLd<@d?f?37}6)S9|OVKV$TU% zsbxLw_%YGHURpWXWcCX39U;WTeve# z+US-#P%Mq-D}mn+v0_E?^7{UFtl19p@6L2oN_iNY%=zVh@FBs;R-~mM&Lp0i=J_UA zc3qUj^b<3!LkX$`3#x>+`cCoa$|{9LAqVbUIR99V*i4!gGrgpnNvQlV`wjglpJK9l zD+4Nogz4yQA5wM(fx|3+T%H^;JogWbXYwLtkk)fB@*GPnvj$KN_{*KBRl2{H9J zhpxjozC*4r6Z_yi7+ZApO%}{ zBO_491fcDeuMnZu?#)WO6ec{zont}?#ujxYOfev=pgaM2!NSj-!Et3R<$P|#MH3t- zNFoNw7-kC>I%-K=JaV};#p9U@%F$rS%9g19w9S&A`(fXngMP#Y`F{(2iv6ODXR{(=3f>L%DG! zEscP#T$#3*wF}A+u56}w{OAV_y5TAL-g|O@$B2F`jK>>0N(PFdl)}d~IV$*VunB_t zPb}r{$$a*o{wMAsb|*NK%H;1mpn*rdm5&62Q3!mBl-kZd`xkQ@&fNw;|lsf6|n&941=c$ER<2(n?!^sWNk1>+{82e}MUqtOdq-)(18^9D*1 z-!B&6!7yncbX<%;aUnq#W&{*?g>evvH~jm#Fr*vGXfyKO9Q*F=Fo*|niVfbxR@QuR zFQPhpOR(tp2>3fw-B$RcSVq*)ddKclZ5~jrMi6MMfBY6J_|GXDXsQOWX91WatCmaQCRz$s%oBU8)FGE zn=?04cYZM~*5)Lct@FNy`)4B^ba+3LDM6PLcDwp@;}^}>A8Rwd^QUJQ$y2Dl8puEE zVazw4mzw54vqMC*b|H(g?sWiL!{0D`%*3_pLVu2Ns-vTNHBVLQU|hPS6=`scvS2Zl z4%k08yxJl!BsP_fkSKSXJ@zwkm5@pIYoj(t_l?e3@JgO7npR2|EsDJ??d9d@g^y%i zXNzocBT*vi_7*!JeH9uW<2#rcS0oi<106H!=OI+yh#_2iquW5Tuu z9m2RbOfSKj0pjGzbG4UZ3hmVRV0sbks%BF7>v@bC)CBrdIDjA(5mfFhiwH zc6BT!N3YkooZr0b>xGmW+2ygSmY>T!Hnp-pEe8`|V>2~_Tu)Hmnxo%hzwBt1cu%V+ zIP;Z*tZc#e+qM>fBH2KVsR56$9ddXp~{k-QdOP*bGT2N=W9UU z_Z(#y0}{36w*DSB!_3)fR#|T>qA89tl7`#D2^p3yUj9hx^cKmx&IwdgN=m@HfaJiC zxbvcIr*Qy9HaiodwrfJ((i_`eMEy+mkF6f{!y2W99Mo$rUzF5}$zB>4L9S6_q^z|{ z2NkM7<$CQ+z`K1Bg0UHF*bBxF_)z2&Kw&umOyZH`19Ph|47F zxW2|A6w&`I%i-K&vTdPl=(bG&v6AN-w0r0S^VEK$nk%?MOi7tuIEF7-u6x&-qq__n zdnF&2iRx*6W=hrhlE>rhg@%;3MsorzyNvZ?Em?$}B?J@wCFe-Yh7Oq#oB#J5oG)DU z5%JghncTK?N2a-oHB3~Z=~hG?X6E;UPv_}z-&!mIk*PZ>niNMT4Kq?8&1apqjHn-X zn4$Gs_I%Ys`se2YGdUG!F+r>4gHpdkw@K~LvQ4AdY>`DWqDIdyFyIrxVT)LG%7L$^ zb}p;I!DTAfu_UMD`iO8ufw&~MX$h>ZHkK7rUN7b+8oG5qOtl{Fe6L`Pk>Ex~jzfgH zqiWC|YPp9az6LNvk-b7|yZuQ0GgtLC{#a%&ftEyjcQB*b z(l9IT1b)uU-OKL{Mct?I7r7c32V>Mr`+IrCU!iZBfQ(o#SY+QIghMX_BG7*FOD3Zl zg&@9)+@x1677z$!*6+VnUe4lxn+9Nw%}&OyA8a1BoAOK|dss7%f#_(J+ijllGv#SS zKP?t6Y=yl(r+_0@t7spykXmFkCNZo6bar>4uFn|(JKs2=nqReq8KsI&CAYI`j0)Md za+YvMAsBq?BvoTjNFu;g-MK*QjH1RtG%9mH2yjgwD_W-}8rRO_ykriDaHB}v<@&`x z!PD2d*Kr<;5`!8s zT?9N`t@$v;x=Dt0z&**aL}*J%Ko} z>1OG-c(>R*ddJ)pZ>ZNoxmT0i)>j|4?7fao9QMA(Mogz}lP2HoZBy}9iRa_Ge%??MY&vN2MPN?a_kk{H2BM^k-bd?C0c-yVDd0D{o>l)*{hwY&ohKS zXcVQf`P+jpt8d$Qhmc6YORc-#=X*arKUr zJb!kQTFyB^Br93!A67=w1Sb_J5kQ?D`c2{+;I?ZsS}Ib-^t(h7RS|BG1Saho5gIkk z&u=x-M6sc?BuMnEa)|2P&oY6WZko&Iigu~ZoD_3eSP2>1fQi)RtE^++ZI5HFo2BE7 zE9dQ&gF_-Kh+Z}Qds~E%7evH%EhBf6*_rF`b}Z<;1x@SCxsBB*NAh%T3*#AE2NNQ^fMBj^xezQ|7(BTT!XYe)op4%BZzRT5aZ2gABBq_zrG-%a$;VcVtkf>C(I) z*NuWg;LJ7u?wm_wf%ew*dUQd*_mIcjdth4gUME*-I2urV-{;U7ugqn;{G3uKdwTAC zRL+X+y4P8y*Tb;h4EtSuqj;naeP(}zSPkJNX^dpUEi3d?$x5x#N7FaLcEeQfWo9$%~tLF;C)Ss!?5K0a|>&=^3+Ji zOt;LPK_o8IW_2e6y`}?GQ@3SQ9BNVjXK?U{2Gnq9!FboLYT^sQRM7&vZ@0bko0*Qn zY-W;V8#QMKxSGFTa_XV4jS&a}su9LH^H1>IIdtwEKP)xq~xR_5|I3{41Si9kCt$tLQw2jU9ZoU@@_tDdOD2NPjq?+is@kcQHrN#Jcxz$n_yYRyB zs0Z`oO6+l1>3DzL;~CYEESW;tqm?fHJO!4|acjcbnk$Fy)2ejg5tHwm%h8YtnRj8E znJ;)6S_#Y_%!qjh%{?_G#JZ8fq8jd4F521z=|?}O?8s0m2;M8torJ$4-fN%Tt}#{n z$!;(PzPr?^O!waFuR9t)9`!7HkiW{h>%B}w2|kpmC7_FTQwujK>YCP1>eUn>=?`0# z@gJ&~9II#?znwSSVu&H)sK~uqobc{-{8R|~P~$TaA1xfm;7I$mg^`uZtKh+N8SU@B za}QV|ek3puv|x9f$1F|^uePy{zo{^>o}aR9t6X};diP6O%}sxX6*83p?Fr6$=P`Hg zJ%7SFV@aMpL`)=)Ey7?EYI#lW>!RT)TZWNcnX)mLt&by#&Fjb8_LS4u+YnEc;X;Ja z*UDy_8lBgwxOJQITEu%FTI?3hbVPETiZKvb5heg$UnO?ib-TT`NFzl(M2L7a_H2Hu z#(u_+uDxXv@4}VT3MY=y?dMObZx|#jpxZO2;T)QT~FT8)`$n!$*vYW}? zeWBGS#IETL^U4!%`Q4_5rR2LR>s?8Ef*pO|0mkuP!OIG!(PeU@8BS7aGPS%wK%tbb z<=U6NLJNlOmdnFxB{Du9lZmk;N;eZS@XkHtc70LtQ!yL!nOl#-XU&-{5Q?gyADN(o zYs6hNUqdQIoR$9bOear>TBxv!p7DKk%Hc_N(<{pU&-s0AeoF$k6m}gp9l%|s!FP`` zx_1-d<0pr_1!G0fU-;S8Fvr(B(^$ZuK+pyVDakeCs-aaUi+SCsT}UNtv6 z(>afg{8L`u(_`&0+%JLL7THO+j%TdI?h%JZY6c9rNZiSii{Y+#MT;FeO9aG6{1u}a zr_GSYE8pRFY=_^{!wIJab3brBzH?GF-?1tzXm7iW&c|f4`REcMaw&7}p_7DPgR2$! zd+PsQ1C08JW0YsYNH#a0-;^$%fuKuGeEVODm-$nF5zimk^dlLypSLTgr^V)J@3_qG zH`A-M`CT8)k4qdlErZv$W;oWa`9o|Qs?yJQYOy!ysho86H?X>U#FQZBBvJKO_zsQS z(^fN(HIw?M;gH_oA+%a_-YtRTa*^fvR_p$V%$GdS{p+t+ktl@~uh=YspU&T0-W24z zIeUy43Yad=(i~S+H}kw|=jhD>Y4#ojET&b`qfn8d6)y5jb8mX$b~WlJBQH7b5cwpT zQ!-8C%-qyf7ObXN{sLb$4qryE`$c06MzZ=DBvbgQ?uCO<&wbvV11Z^V-m9;4tfp}_ z>;*uUlGxdze-e))RJVO_+n)N$(PDN}sH9jFoLN-l%aZG!SZxk1v?snfwe*1W06H@pHTet~$7btDm<9I-?e6w`j z9>B5-8ykwF1E7g_h2AXC7bGqD)~4dd{Q^;8DbD$rydd%;4g}ivv!U?LMyga~lffyM z<(u2q!tBPjgV3@!1Y5w zMezrL3sPYv#%cbCOApWak|hSE{;Z+>LsMPfDMFEs1;>tEE$U#BhC2=)O9Ei2}!zIlsceudzvys^&&EUvG|Rkhde& zADbI0jyo=f43qWqte_v^*J=k4*wR_$?;rF7o-d2`&qoMQnFh4|3t#;?A^x)|qT&>3 zh>Cxm`bp0FZ!r^2j55>riNwFA&mT`in5n-iTWv(9|65FeD#JvuvMcvzk$-Nu9|>cW zi@48v75^GC&szK=3iL z)dBzCV));ki}c{~KSd)l6R^Mi`Xh(@_5U;xRzD^}NcO+mqRs?sqVX@x)PIW;VD(Et z-&6W`TbK!8O=REstnhEK9ISqFNKnRqw}lW^ggS}y+y7}|KCFrPpKkxBE$FZ!n4g1b z{zt3|JHx1oJ^Z~f{zoCA!LT9-kr!kBM_lY5Bwn2J_@CwP?+WIK!-_x;wEg)%Vs+Rs zP*?W*W3l|}Y2~l5B7((u-~W&J_b^~C68X12iH=6%z f0{#EAXskSGh7kf;_l^>t!G5xm?<6Y3jXwQ9#)5?? diff --git a/docs/assets/js/23.05b059b6.js b/docs/assets/js/23.cd7748bf.js similarity index 97% rename from docs/assets/js/23.05b059b6.js rename to docs/assets/js/23.cd7748bf.js index 160bef9048..49203ee514 100644 --- a/docs/assets/js/23.05b059b6.js +++ b/docs/assets/js/23.cd7748bf.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[23],{305:function(r,e,t){"use strict";t.r(e);var n=t(14),a=Object(n.a)({},(function(){var r=this,e=r._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":r.$parent.slotKey}},[e("h1",{attrs:{id:"about"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#about"}},[r._v("#")]),r._v(" About")]),r._v(" "),e("p",[r._v("Caliban is a project created by Pierre Ricadat aka "),e("a",{attrs:{href:"https://github.com/ghostdogpr",target:"_blank",rel:"noopener noreferrer"}},[r._v("@ghostdogpr"),e("OutboundLink")],1),r._v(".")]),r._v(" "),e("p",[r._v("Current maintainers:")]),r._v(" "),e("ul",[e("li",[e("a",{attrs:{href:"https://github.com/ghostdogpr",target:"_blank",rel:"noopener noreferrer"}},[r._v("@ghostdogpr"),e("OutboundLink")],1)]),r._v(" "),e("li",[e("a",{attrs:{href:"https://github.com/paulpdaniels",target:"_blank",rel:"noopener noreferrer"}},[r._v("@paulpdaniels"),e("OutboundLink")],1)]),r._v(" "),e("li",[e("a",{attrs:{href:"https://github.com/frekw",target:"_blank",rel:"noopener noreferrer"}},[r._v("@frekw"),e("OutboundLink")],1)]),r._v(" "),e("li",[e("a",{attrs:{href:"https://github.com/kyri-petrou",target:"_blank",rel:"noopener noreferrer"}},[r._v("@kyri-petrou"),e("OutboundLink")],1)])]),r._v(" "),e("p",[r._v("The name is inspired by the SF novel and tv series "),e("a",{attrs:{href:"https://en.wikipedia.org/wiki/Caliban%27s_War",target:"_blank",rel:"noopener noreferrer"}},[r._v("The Expanse"),e("OutboundLink")],1),r._v(".")]),r._v(" "),e("p",[e("strong",[r._v("Thanks")]),r._v(":")]),r._v(" "),e("ul",[e("li",[e("a",{attrs:{href:"https://github.com/deckerst",target:"_blank",rel:"noopener noreferrer"}},[r._v("@deckerst"),e("OutboundLink")],1),r._v(" for the logo")]),r._v(" "),e("li",[e("a",{attrs:{href:"https://github.com/yoohaemin",target:"_blank",rel:"noopener noreferrer"}},[r._v("@yoohaemin"),e("OutboundLink")],1),r._v(", "),e("a",{attrs:{href:"https://github.com/adamgfraser",target:"_blank",rel:"noopener noreferrer"}},[r._v("@adamgfraser"),e("OutboundLink")],1),r._v(" and "),e("a",{attrs:{href:"https://github.com/jdegoes",target:"_blank",rel:"noopener noreferrer"}},[r._v("@jdegoes"),e("OutboundLink")],1),r._v(" for the early feedback")]),r._v(" "),e("li",[r._v("the "),e("a",{attrs:{href:"https://morpheusgraphql.com/",target:"_blank",rel:"noopener noreferrer"}},[r._v("Morpheus"),e("OutboundLink")],1),r._v(" library in Haskell for the inspiration leading to the GraphQL backend implementation")]),r._v(" "),e("li",[r._v("the "),e("a",{attrs:{href:"https://github.com/dillonkearns/elm-graphql",target:"_blank",rel:"noopener noreferrer"}},[r._v("elm-graphql"),e("OutboundLink")],1),r._v(" library for the inspiration leading to the GraphQL client implementation")]),r._v(" "),e("li",[r._v("all Caliban's "),e("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/graphs/contributors",target:"_blank",rel:"noopener noreferrer"}},[r._v("contributors"),e("OutboundLink")],1),r._v("!")])])])}),[],!1,null,null,null);e.default=a.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[23],{304:function(r,e,t){"use strict";t.r(e);var n=t(14),a=Object(n.a)({},(function(){var r=this,e=r._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":r.$parent.slotKey}},[e("h1",{attrs:{id:"about"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#about"}},[r._v("#")]),r._v(" About")]),r._v(" "),e("p",[r._v("Caliban is a project created by Pierre Ricadat aka "),e("a",{attrs:{href:"https://github.com/ghostdogpr",target:"_blank",rel:"noopener noreferrer"}},[r._v("@ghostdogpr"),e("OutboundLink")],1),r._v(".")]),r._v(" "),e("p",[r._v("Current maintainers:")]),r._v(" "),e("ul",[e("li",[e("a",{attrs:{href:"https://github.com/ghostdogpr",target:"_blank",rel:"noopener noreferrer"}},[r._v("@ghostdogpr"),e("OutboundLink")],1)]),r._v(" "),e("li",[e("a",{attrs:{href:"https://github.com/paulpdaniels",target:"_blank",rel:"noopener noreferrer"}},[r._v("@paulpdaniels"),e("OutboundLink")],1)]),r._v(" "),e("li",[e("a",{attrs:{href:"https://github.com/frekw",target:"_blank",rel:"noopener noreferrer"}},[r._v("@frekw"),e("OutboundLink")],1)]),r._v(" "),e("li",[e("a",{attrs:{href:"https://github.com/kyri-petrou",target:"_blank",rel:"noopener noreferrer"}},[r._v("@kyri-petrou"),e("OutboundLink")],1)])]),r._v(" "),e("p",[r._v("The name is inspired by the SF novel and tv series "),e("a",{attrs:{href:"https://en.wikipedia.org/wiki/Caliban%27s_War",target:"_blank",rel:"noopener noreferrer"}},[r._v("The Expanse"),e("OutboundLink")],1),r._v(".")]),r._v(" "),e("p",[e("strong",[r._v("Thanks")]),r._v(":")]),r._v(" "),e("ul",[e("li",[e("a",{attrs:{href:"https://github.com/deckerst",target:"_blank",rel:"noopener noreferrer"}},[r._v("@deckerst"),e("OutboundLink")],1),r._v(" for the logo")]),r._v(" "),e("li",[e("a",{attrs:{href:"https://github.com/yoohaemin",target:"_blank",rel:"noopener noreferrer"}},[r._v("@yoohaemin"),e("OutboundLink")],1),r._v(", "),e("a",{attrs:{href:"https://github.com/adamgfraser",target:"_blank",rel:"noopener noreferrer"}},[r._v("@adamgfraser"),e("OutboundLink")],1),r._v(" and "),e("a",{attrs:{href:"https://github.com/jdegoes",target:"_blank",rel:"noopener noreferrer"}},[r._v("@jdegoes"),e("OutboundLink")],1),r._v(" for the early feedback")]),r._v(" "),e("li",[r._v("the "),e("a",{attrs:{href:"https://morpheusgraphql.com/",target:"_blank",rel:"noopener noreferrer"}},[r._v("Morpheus"),e("OutboundLink")],1),r._v(" library in Haskell for the inspiration leading to the GraphQL backend implementation")]),r._v(" "),e("li",[r._v("the "),e("a",{attrs:{href:"https://github.com/dillonkearns/elm-graphql",target:"_blank",rel:"noopener noreferrer"}},[r._v("elm-graphql"),e("OutboundLink")],1),r._v(" library for the inspiration leading to the GraphQL client implementation")]),r._v(" "),e("li",[r._v("all Caliban's "),e("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/graphs/contributors",target:"_blank",rel:"noopener noreferrer"}},[r._v("contributors"),e("OutboundLink")],1),r._v("!")])])])}),[],!1,null,null,null);e.default=a.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/24.4e724191.js b/docs/assets/js/24.4e724191.js deleted file mode 100644 index cde1429b76..0000000000 --- a/docs/assets/js/24.4e724191.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[24],{304:function(t,a,s){"use strict";s.r(a);var e=s(14),r=Object(e.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"getting-started"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#getting-started"}},[t._v("#")]),t._v(" Getting Started")]),t._v(" "),a("p",[a("strong",[t._v("Caliban")]),t._v(" is a purely functional library for creating GraphQL servers and clients in Scala.")]),t._v(" "),a("p",[t._v("For more details on Caliban Client, see the "),a("RouterLink",{attrs:{to:"/docs/client.html"}},[t._v("dedicated section")]),t._v(". The rest of this page is about the backend part of the library.")],1),t._v(" "),a("p",[t._v("The design principles of Caliban are the following:")]),t._v(" "),a("ul",[a("li",[a("strong",[t._v("high performance")]),t._v(": while every public interface is pure and immutable, library internals have been optimized for speed, providing by far the best performance of any Scala GraphQL library.")]),t._v(" "),a("li",[a("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(" "),a("li",[a("strong",[t._v("excellent interoperability")]),t._v(": out-of-the-box support for major HTTP server libraries ("),a("a",{attrs:{href:"https://http4s.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("http4s"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://doc.akka.io/docs/akka-http/current/index.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Akka HTTP"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/apache/incubator-pekko-http",target:"_blank",rel:"noopener noreferrer"}},[t._v("Pekko HTTP"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://www.playframework.com/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Play"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/dream11/zio-http",target:"_blank",rel:"noopener noreferrer"}},[t._v("ZIO HTTP"),a("OutboundLink")],1),t._v("), effect types (Future, "),a("a",{attrs:{href:"https://zio.dev/",target:"_blank",rel:"noopener noreferrer"}},[t._v("ZIO"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://typelevel.org/cats-effect/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Cats Effect"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://monix.io/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Monix"),a("OutboundLink")],1),t._v("), Json libraries ("),a("a",{attrs:{href:"https://circe.github.io/circe/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Circe"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/plokhotnyuk/jsoniter-scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("Jsoniter"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/playframework/play-json",target:"_blank",rel:"noopener noreferrer"}},[t._v("Play Json"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/zio/zio-json",target:"_blank",rel:"noopener noreferrer"}},[t._v("ZIO Json"),a("OutboundLink")],1),t._v("), various integrations ("),a("a",{attrs:{href:"https://github.com/apollographql/apollo-tracing",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Tracing"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://www.apollographql.com/docs/federation/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Federation"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://tapir.softwaremill.com/en/latest/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Tapir"),a("OutboundLink")],1),t._v(", etc.) and more.")])]),t._v(" "),a("h2",{attrs:{id:"a-simple-example"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#a-simple-example"}},[t._v("#")]),t._v(" A simple example")]),t._v(" "),a("p",[t._v("First, add the following dependency to your "),a("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v("\n")])])]),a("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(" "),a("p",[t._v("Let's say we have a class "),a("code",[t._v("Character")]),t._v(" and 2 functions: "),a("code",[t._v("getCharacters")]),t._v(" and "),a("code",[t._v("getCharacter")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" age"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" getCharacters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Nil\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" getCharacter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n")])])]),a("p",[t._v("Let's create a case class named "),a("code",[t._v("Queries")]),t._v(" that will represent our API, with 2 fields named and modeled after the functions we want to expose (a "),a("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(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// schema")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" CharacterName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n character"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CharacterName "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// resolver")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" queries "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("getCharacters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" args "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" getCharacter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("The next step is creating our GraphQL API definition. First, we wrap our query resolver inside a "),a("code",[t._v("RootResolver")]),t._v(", the root object that contains queries, mutations and subscriptions. Only queries are mandatory.\nThen we can call the "),a("code",[t._v("graphQL")]),t._v(" function which will turn our simple resolver value into a GraphQL API definition.\nThe whole schema will be derived at compile time, meaning that if it compiles, it will be able to serve it.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("You can use "),a("code",[t._v("api.render")]),t._v(" to visualize the schema generated, in this case:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("age")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Queries")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("characters")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("character")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("In order to process requests, you need to turn your API into an interpreter, which can be done easily by calling "),a("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 "),a("RouterLink",{attrs:{to:"/docs/middleware.html"}},[t._v("Middleware")]),t._v(" for more info).\nCreating the interpreter may fail with a "),a("code",[t._v("ValidationError")]),t._v(" if some type is found invalid.")],1),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n interpreter "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interpreter\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(" interpreter\n")])])]),a("p",[t._v("Now you can call "),a("code",[t._v("interpreter.execute")]),t._v(" with a given GraphQL query, and you will get an "),a("code",[t._v("ZIO[R, Nothing, GraphQLResponse[CalibanError]]")]),t._v(" as a response, with "),a("code",[t._v("GraphQLResponse")]),t._v(" defined as follows:")]),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(" GraphQLResponse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v("E"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("data"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ResponseValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" errors"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("E"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("Use "),a("code",[t._v("ResponseValue#toString")]),t._v(" to get the JSON representation of the result.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" query "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token triple-quoted-string string"}},[t._v('"""\n {\n characters {\n name\n }\n }"""')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n interpreter "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interpreter\n result "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" interpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("execute"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n _ "),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("ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("debug"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),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"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("A "),a("code",[t._v("CalibanError")]),t._v(" can be:")]),t._v(" "),a("ul",[a("li",[t._v("a "),a("code",[t._v("ParsingError")]),t._v(": the query has invalid syntax")]),t._v(" "),a("li",[t._v("a "),a("code",[t._v("ValidationError")]),t._v(": the query was parsed but does not match the schema")]),t._v(" "),a("li",[t._v("an "),a("code",[t._v("ExecutionError")]),t._v(": an error happened while executing the query")])]),t._v(" "),a("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.\nThe "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/adapters/http4s",target:"_blank",rel:"noopener noreferrer"}},[t._v("caliban-http4s"),a("OutboundLink")],1),t._v(" module provides an "),a("code",[t._v("Http4sAdapter")]),t._v(" that exposes an interpreter over HTTP and WebSocket using http4s. There are also similar adapters for Akka HTTP, Pekko HTTP, Play and zio-http.\nRead more on the "),a("RouterLink",{attrs:{to:"/docs/adapters.html"}},[t._v("adapters' documentation")]),t._v(".")],1),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("Combining GraphQL APIs")]),t._v(" "),a("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 "),a("code",[t._v("GraphQL")]),t._v(" objects using the "),a("code",[t._v("|+|")]),t._v(" operator.")]),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(" api1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api2 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\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(" api1 "),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(" api2\n")])])]),a("p",[t._v("You can use "),a("code",[t._v(".rename")]),t._v(" to change the names of the generated root types.")])]),t._v(" "),a("h2",{attrs:{id:"mutations"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#mutations"}},[t._v("#")]),t._v(" Mutations")]),t._v(" "),a("p",[t._v("Creating mutations is the same as queries, except you pass them as the second argument to "),a("code",[t._v("RootResolver")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:nest:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Task\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(" CharacterArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Mutations"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("deleteCharacter"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CharacterArgs "),a("span",{pre:!0,attrs:{class:"token keyword"}},[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("Boolean")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" mutations "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Mutations"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" mutations"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h2",{attrs:{id:"subscriptions"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#subscriptions"}},[t._v("#")]),t._v(" Subscriptions")]),t._v(" "),a("p",[t._v("Similarly, subscriptions are passed as the third argument to "),a("code",[t._v("RootResolver")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:compile-only extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("stream"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ZStream\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(" Subscriptions"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("deletedCharacter"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ZStream"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" subscriptions "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Subscriptions"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" mutations"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" subscriptions"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("All the fields of the subscription root case class MUST return "),a("code",[t._v("ZStream")]),t._v(" or "),a("code",[t._v("? => ZStream")]),t._v(" objects. When a subscription request is received, an output stream of "),a("code",[t._v("ResponseValue")]),t._v(" (a "),a("code",[t._v("StreamValue")]),t._v(") will be returned wrapped inside an "),a("code",[t._v("ObjectValue")]),t._v(".")]),t._v(" "),a("h2",{attrs:{id:"serving-over-http"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#serving-over-http"}},[t._v("#")]),t._v(" Serving over HTTP")]),t._v(" "),a("p",[t._v("The easiest (and most performant!) way to expose your API over HTTP is to use the optional "),a("code",[t._v("caliban-quick")]),t._v(" module:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-quick"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v("\n")])])]),a("p",[t._v("And then you can serve your GraphQL API over HTTP using a single command:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:compile-only extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("quick"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_ "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Adds syntax to `GraphQL`")]),t._v("\n\napi"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("runServer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n port "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("8080")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n apiPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/api/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n graphiqlPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/graphiql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("And that's it - now you have a fully functional GraphQL server running on port 8080!")]),t._v(" "),a("h2",{attrs:{id:"interop-with-3rd-party-libraries"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#interop-with-3rd-party-libraries"}},[t._v("#")]),t._v(" Interop with 3rd-party libraries")]),t._v(" "),a("p",[t._v("If you have any specific server requirements or need to interop with other libraries, Caliban offers a wide range of modules to help you do that.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-http4s"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// routes for http4s")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-akka-http"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// routes for akka-http")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-play"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// routes for play")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-zio-http"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// routes for zio-http")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-cats"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// interop with cats effect")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-monix"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// interop with monix")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-tapir"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// interop with tapir")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-federation"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// interop with apollo federation")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-tracing"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// interop with zio-telemetry")]),t._v("\n")])])]),a("p",[t._v("Support for JSON encoding / decoding of the inputs and responses for tapir-based adapters is enabled by adding "),a("strong",[t._v("one")]),t._v(" of the following dependencies to your "),a("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.softwaremill.sttp.tapir"')]),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('"tapir-json-circe"')]),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.11"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Circe")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.softwaremill.sttp.tapir"')]),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('"tapir-jsoniter-scala"')]),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.11"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Jsoniter")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.softwaremill.sttp.tapir"')]),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('"tapir-json-play"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1.2.11"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Play JSON")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.softwaremill.sttp.tapir"')]),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('"tapir-json-zio"')]),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.11"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ZIO JSON")]),t._v("\n")])])]),a("p",[t._v("And then later in your code (you only need one!):")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("json"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("circe"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("json"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("jsoniter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("json"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("play"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("json"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n")])])]),a("p",[t._v("For more info on the adapters and the JSON implementations, see "),a("RouterLink",{attrs:{to:"/docs/adapters.html#json-handling"}},[t._v("here")]),t._v(".")],1)])}),[],!1,null,null,null);a.default=r.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/24.d41ca9d3.js b/docs/assets/js/24.d41ca9d3.js new file mode 100644 index 0000000000..0cd0d42e52 --- /dev/null +++ b/docs/assets/js/24.d41ca9d3.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[24],{305:function(t,a,s){"use strict";s.r(a);var e=s(14),r=Object(e.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"getting-started"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#getting-started"}},[t._v("#")]),t._v(" Getting Started")]),t._v(" "),a("p",[a("strong",[t._v("Caliban")]),t._v(" is a purely functional library for creating GraphQL servers and clients in Scala.")]),t._v(" "),a("p",[t._v("For more details on Caliban Client, see the "),a("RouterLink",{attrs:{to:"/docs/client.html"}},[t._v("dedicated section")]),t._v(". The rest of this page focuses on the backend part of the library.")],1),t._v(" "),a("p",[t._v("The design principles of Caliban are the following:")]),t._v(" "),a("ul",[a("li",[a("strong",[t._v("high performance")]),t._v(": while all public interfaces are pure and immutable, the library's internals are optimized for speed, offering the best performance of any Scala GraphQL library.")]),t._v(" "),a("li",[a("strong",[t._v("minimal amount of boilerplate")]),t._v(": you don't need to manually define schemas for every type in your API. Let the compiler handle the tedious work.")]),t._v(" "),a("li",[a("strong",[t._v("excellent interoperability")]),t._v(": out-of-the-box support for major HTTP server libraries ("),a("a",{attrs:{href:"https://http4s.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("http4s"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://doc.akka.io/docs/akka-http/current/index.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Akka HTTP"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/apache/incubator-pekko-http",target:"_blank",rel:"noopener noreferrer"}},[t._v("Pekko HTTP"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://www.playframework.com/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Play"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/dream11/zio-http",target:"_blank",rel:"noopener noreferrer"}},[t._v("ZIO HTTP"),a("OutboundLink")],1),t._v("), effect types (Future, "),a("a",{attrs:{href:"https://zio.dev/",target:"_blank",rel:"noopener noreferrer"}},[t._v("ZIO"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://typelevel.org/cats-effect/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Cats Effect"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://monix.io/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Monix"),a("OutboundLink")],1),t._v("), JSON libraries ("),a("a",{attrs:{href:"https://circe.github.io/circe/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Circe"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/plokhotnyuk/jsoniter-scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("Jsoniter"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/playframework/play-json",target:"_blank",rel:"noopener noreferrer"}},[t._v("Play Json"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/zio/zio-json",target:"_blank",rel:"noopener noreferrer"}},[t._v("ZIO Json"),a("OutboundLink")],1),t._v("), plus various integrations ("),a("a",{attrs:{href:"https://github.com/apollographql/apollo-tracing",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Tracing"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://www.apollographql.com/docs/federation/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Federation"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://tapir.softwaremill.com/en/latest/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Tapir"),a("OutboundLink")],1),t._v(", etc.) and more.")])]),t._v(" "),a("h2",{attrs:{id:"a-simple-schema"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#a-simple-schema"}},[t._v("#")]),t._v(" A simple schema")]),t._v(" "),a("p",[t._v("First, add the following dependency to your "),a("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v("\n")])])]),a("p",[t._v("Creating a GraphQL API with Caliban is as simple as creating a case class in Scala.\nIndeed, the whole GraphQL schema will be derived from a case class hierarchy (its fields and the other types it references), and the resolver is just an instance of that case class.")]),t._v(" "),a("p",[t._v("Let's say we have a class "),a("code",[t._v("Character")]),t._v(" and 2 functions: "),a("code",[t._v("getCharacters")]),t._v(" and "),a("code",[t._v("getCharacter")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" age"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" getCharacters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Nil\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" getCharacter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n")])])]),a("p",[t._v("Let's create a case class named "),a("code",[t._v("Queries")]),t._v(" that will represent our API, with 2 fields named and modeled after the functions we want to expose.\nWe then create a value of this class that calls our actual functions. This is our resolver.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// schema")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" CharacterName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n character"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CharacterName "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// resolver")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" queries "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("getCharacters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" args "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" getCharacter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("The next step is creating our GraphQL API definition.")]),t._v(" "),a("p",[t._v("First, we wrap our query resolver inside a "),a("code",[t._v("RootResolver")]),t._v(", the root object that contains queries, mutations and subscriptions. Only queries are mandatory.\nThen we call the "),a("code",[t._v("graphQL")]),t._v(" function which will turn our simple resolver value into a GraphQL API definition.\nThe whole schema will be derived at compile time, meaning that if it compiles, it will be able to serve it.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("You can use "),a("code",[t._v("api.render")]),t._v(" to visualize the schema generated, in this case:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("age")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Queries")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("characters")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("character")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"serving-over-http"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#serving-over-http"}},[t._v("#")]),t._v(" Serving over HTTP")]),t._v(" "),a("p",[t._v("Once you have your API object, you can turn it into an interpreter ("),a("code",[t._v("api.interpreter")]),t._v(") and start processing requests ("),a("code",[t._v("interpreter.execute")]),t._v(").\nThe interpreter is not tied any web framework, so you are free to expose this function using the protocol and library of your choice.")]),t._v(" "),a("p",[t._v("The easiest (and most performant!) way to expose your API over HTTP is to use the optional "),a("code",[t._v("caliban-quick")]),t._v(" module based on "),a("a",{attrs:{href:"https://github.com/zio/zio-http",target:"_blank",rel:"noopener noreferrer"}},[t._v("zio-http"),a("OutboundLink")],1),t._v(".")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-quick"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v("\n")])])]),a("p",[t._v("You can then serve your GraphQL API over HTTP using a single command:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:compile-only extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("quick"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_ "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// adds extension methods to `api`")]),t._v("\n\napi"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("unsafe"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("runServer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n port "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("8080")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n apiPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/api/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("And that's it - now you have a fully functional GraphQL server running on port 8080!")]),t._v(" "),a("h2",{attrs:{id:"interop-with-3rd-party-libraries"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#interop-with-3rd-party-libraries"}},[t._v("#")]),t._v(" Interop with 3rd-party libraries")]),t._v(" "),a("p",[t._v("If you have any specific server requirements or need to interop with other libraries, Caliban offers a wide range of modules to help you do that.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-http4s"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// routes for http4s")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-akka-http"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// routes for akka-http")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-pekko-http"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// routes for pekko-http")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-play"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// routes for play")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-cats"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// interop with cats-effect")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-monix"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// interop with monix")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-tapir"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// interop with tapir")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-federation"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// apollo federation")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-reporting"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// apollo schema reporting")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-tracing"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// open-telemetry")]),t._v("\n")])])]),a("p",[t._v("Support for JSON encoding / decoding of the inputs and responses for tapir-based adapters is enabled by adding "),a("strong",[t._v("one")]),t._v(" of the following dependencies to your "),a("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.softwaremill.sttp.tapir"')]),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('"tapir-json-circe"')]),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.11"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// circe")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.softwaremill.sttp.tapir"')]),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('"tapir-jsoniter-scala"')]),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.11"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// jsoniter")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.softwaremill.sttp.tapir"')]),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('"tapir-json-play"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1.2.11"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// play-json")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.softwaremill.sttp.tapir"')]),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('"tapir-json-zio"')]),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.11"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// zio-json")]),t._v("\n")])])]),a("p",[t._v("And then later in your code (you only need one!):")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("json"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("circe"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("json"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("jsoniter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("json"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("play"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("json"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n")])])]),a("p",[t._v("For more info on the adapters and the JSON implementations, see "),a("RouterLink",{attrs:{to:"/docs/adapters.html#json-handling"}},[t._v("here")]),t._v(".")],1)])}),[],!1,null,null,null);a.default=r.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/25.693cf732.js b/docs/assets/js/25.693cf732.js deleted file mode 100644 index 19136bccee..0000000000 --- a/docs/assets/js/25.693cf732.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[25],{306:function(t,a,e){"use strict";e.r(a);var s=e(14),r=Object(s.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"http-adapters"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#http-adapters"}},[t._v("#")]),t._v(" Http Adapters")]),t._v(" "),a("p",[t._v('Once you have an interpreter able to execute GraphQL queries, you usually want to expose it using an HTTP API.\nCaliban comes with a few "ready-to-use" components (called "adapters") to expose your API with the most popular HTTP libraries.')]),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("`QuickAdapter`")]),t._v(" "),a("p",[t._v("Starting with v2.4.3, Caliban provides the opinionated "),a("RouterLink",{attrs:{to:"/docs/adapters.html#high-performance-quickadapter"}},[t._v("QuickAdapter")]),t._v("\nthat favours ease-of-use and performance at the expense of customizability.")],1),t._v(" "),a("p",[t._v("If you want the best possible performance, make sure to check it out!")])]),t._v(" "),a("h2",{attrs:{id:"built-in-tapir-adapters"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#built-in-tapir-adapters"}},[t._v("#")]),t._v(" Built-in tapir adapters")]),t._v(" "),a("p",[t._v("Under the hood, adapters use the "),a("a",{attrs:{href:"https://tapir.softwaremill.com/en/latest/",target:"_blank",rel:"noopener noreferrer"}},[t._v("tapir"),a("OutboundLink")],1),t._v(" library, so you can easily create a custom adapter with anything that tapir supports.")]),t._v(" "),a("p",[t._v("The following adapters are provided:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("Http4sAdapter")]),t._v(" exposes a route for http4s.")]),t._v(" "),a("li",[a("code",[t._v("ZHttpAdapter")]),t._v(" exposes a route for zio-http. This one doesn't support uploads yet.")]),t._v(" "),a("li",[a("code",[t._v("PlayHttpAdapter")]),t._v(" exposes a route for play.")]),t._v(" "),a("li",[a("code",[t._v("AkkaHttpAdapter")]),t._v(" exposes a route for akka.")]),t._v(" "),a("li",[a("code",[t._v("PekkoHttpAdapter")]),t._v(" exposes a route for pekko.")])]),t._v(" "),a("p",[t._v("To use them, you first need to transform your "),a("code",[t._v("GraphQLInterpreter")]),t._v(" into a new type of interpreter that supports the protocol you want to use.\nThere are 3 of them:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("HttpInterpreter")]),t._v(" follows the "),a("a",{attrs:{href:"https://graphql.org/learn/serving-over-http/#http-methods-headers-and-body",target:"_blank",rel:"noopener noreferrer"}},[t._v("standard GraphQL protocol"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("code",[t._v("HttpUploadInterpreter")]),t._v(" follows the "),a("a",{attrs:{href:"https://github.com/jaydenseric/graphql-multipart-request-spec",target:"_blank",rel:"noopener noreferrer"}},[t._v("GraphQL multipart request protocol"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("code",[t._v("WebSocketInterpreter")]),t._v(" follows the "),a("a",{attrs:{href:"https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md",target:"_blank",rel:"noopener noreferrer"}},[t._v("GraphQL WebSocket protocol"),a("OutboundLink")],1)])]),t._v(" "),a("p",[t._v("These interpreters expose 2 powerful methods:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("configure")]),t._v(" takes a "),a("code",[t._v("Configurator[R]")]),t._v(" which is an alias for "),a("code",[t._v("URIO[R & Scope, Unit]")]),t._v(".\nIt allows configuring the interpreter by running an effect that will run for each request and that can modify the configuration of the running fiber. Built-in configurators such as "),a("code",[t._v("Configurator.setSkipValidation")]),t._v(", "),a("code",[t._v("Configurator.setEnableIntrospection")]),t._v(" and "),a("code",[t._v("Configurator.setQueryExecution")]),t._v(" let you dynamically change the configuration of the interpreter.")]),t._v(" "),a("li",[a("code",[t._v("intercept")]),t._v(" takes an "),a("code",[t._v("Interceptor[-R1, +R]")]),t._v(" which is an alias for "),a("code",[t._v("ZLayer[R1 & ServerRequest, TapirResponse, R]")]),t._v(".\nIt is basically a more powerful version of "),a("code",[t._v("configure")]),t._v(" that gives you access to the incoming request ("),a("code",[t._v("ServerRequest")]),t._v(") and lets you modify the environment of the interpreter (from "),a("code",[t._v("R")]),t._v(" to "),a("code",[t._v("R1")]),t._v("). A typical use case would be to extract an authentication token from the request and eliminate the authentication requirement from the environment if the token is valid. See an example "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/blob/series/2.x/examples/src/main/scala/example/akkahttp/AuthExampleApp.scala#L51",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1),t._v(".")])]),t._v(" "),a("p",[t._v("In addition to that, the "),a("code",[t._v("WebSocketInterpreter")]),t._v(" constructor comes with 2 optional parameters:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("keepAliveInterval")]),t._v(" (default: empty) defines the interval for the server to send keep alive messages to the client")]),t._v(" "),a("li",[a("code",[t._v("webSocketHooks")]),t._v(" (default: empty) gives you some hooks around the WebSocket lifecycle (useful for authentication)")])]),t._v(" "),a("p",[t._v("Once your interpreter is correctly configured, you can use one of these 3 functions exposed by each built-in adapter:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("makeHttpService")]),t._v(" turns an "),a("code",[t._v("HttpInterpreter")]),t._v(" into a route for the corresponding library")]),t._v(" "),a("li",[a("code",[t._v("makeHttpUploadService")]),t._v(" turns an "),a("code",[t._v("HttpUploadInterpreter")]),t._v(" into a route for the corresponding library")]),t._v(" "),a("li",[a("code",[t._v("makeWebSocketService")]),t._v(" turns a "),a("code",[t._v("WebSocketInterpreter")]),t._v(" into a route for the corresponding library")])]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" graphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("AuthToken"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// turn our GraphQL interpreter into an HttpInterpreter")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" noAuthInterpreter"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" HttpInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("AuthToken"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" HttpInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("graphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// define authentication logic (from a ServerRequest, fail or build an AuthToken)")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" auth"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ZLayer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ServerRequest"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" TapirResponse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" AuthToken"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// pass our interceptor to eliminate the AuthToken requirement from the environment")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" authInterpreter"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" HttpUploadInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" httpInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("intercept"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("auth"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// get our route for Akka Http")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" route "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" AkkaHttpAdapter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("default"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("makeHttpService"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("authInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("Want to use something else? Check "),a("a",{attrs:{href:"#make-your-own-adapter"}},[t._v("make your own adapter section")]),t._v("!")]),t._v(" "),a("p",[t._v("Make sure to check the "),a("RouterLink",{attrs:{to:"/docs/examples.html"}},[t._v("examples")]),t._v(" to see the adapters in action.")],1),t._v(" "),a("h2",{attrs:{id:"json-handling"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#json-handling"}},[t._v("#")]),t._v(" Json handling")]),t._v(" "),a("p",[t._v("Caliban comes with JSON encoders and decoders for the following libraries:")]),t._v(" "),a("ul",[a("li",[t._v("circe")]),t._v(" "),a("li",[t._v("jsoniter-scala (JDK 11+ only)")]),t._v(" "),a("li",[t._v("play-json")]),t._v(" "),a("li",[t._v("zio-json")])]),t._v(" "),a("p",[t._v("Since v2.1.0, the adapters are not bound to a specific JSON handler and require the user to add the "),a("RouterLink",{attrs:{to:"/docs/#interop-with-3rd-party-libraries"}},[t._v("corresponding dependency")]),t._v(" in their project and import the implicits in scope when calling the "),a("code",[t._v("makeHttpService")]),t._v(" / "),a("code",[t._v("makeHttpUploadService")]),t._v(" / "),a("code",[t._v("makeWebSocketService")]),t._v(" methods.")],1),t._v(" "),a("p",[t._v("Let's say we want to use "),a("code",[t._v("http4s")]),t._v(" as the server implementation with "),a("code",[t._v("zio-json")]),t._v(" as the json handler. Defining the http4s route is as simple as:")]),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(" http4sRoute "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("json"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n Http4sAdapter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("makeHttpService"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("interpreter"),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("That's it! "),a("code",[t._v("http4sRoute")]),t._v(" is a valid http4s route ready to serve our API.")]),t._v(" "),a("p",[t._v("If you use another json library, you will need to create encoders and decoders for it (which is very simple, you can simply look at the existing ones).\nThe full list of JSON libraries supported by Tapir can be found "),a("a",{attrs:{href:"https://tapir.softwaremill.com/en/latest/endpoint/json.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1)]),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("Known issues: jsoniter-scala")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("makeHttpUploadService")]),t._v(" methods require an implicit of "),a("code",[t._v("JsonCodec[Map[String,Seq[String]]]")]),t._v(" in scope. Jsoniter does not provide\ncodecs for common types by default, which means the user needs to create one. To do so, add the "),a("code",[t._v("jsoniter-scala-macros")]),t._v(" dependency to your project and create one as:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("json"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("jsoniter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("com"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("github"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("plokhotnyuk"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("jsoniter_scala"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("core"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("com"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("github"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("plokhotnyuk"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("jsoniter_scala"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("macros"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" http4sRoute "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("json"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("jsoniter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" codec"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" JsonValueCodec"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Seq"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" JsonCodecMaker"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("make\n\n Http4sAdapter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("makeHttpUploadService"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("interpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"custom-block warning"},[a("p",{staticClass:"custom-block-title"},[t._v("WARNING")]),t._v(" "),a("p",[t._v("To maximize performance, the "),a("strong",[t._v("jsoniter")]),t._v(" codec implementation is stack-recursive. To prevent stack overflow errors, it has a "),a("strong",[t._v("maximum depth limit of 512")]),t._v(".")]),t._v(" "),a("p",[t._v("If your schema contains recursive types and want to use the jsoniter codecs, make sure to also limit the maximum query depth using\nthe "),a("RouterLink",{attrs:{to:"/docs/middleware.html#pre-defined-wrappers"}},[t._v("maxDepth wrapper")]),t._v(".")],1)])]),t._v(" "),a("h2",{attrs:{id:"make-your-own-adapter"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#make-your-own-adapter"}},[t._v("#")]),t._v(" Make your own adapter")]),t._v(" "),a("p",[t._v("All existing adapters are actually using a common adapter under the hood, called "),a("code",[t._v("TapirAdapter")]),t._v(".")]),t._v(" "),a("p",[t._v("This adapter, available in the "),a("code",[t._v("caliban-tapir")]),t._v(" dependency which has the same 3 methods "),a("code",[t._v("makeHttpService")]),t._v(", "),a("code",[t._v("makeHttpUploadService")]),t._v(" and "),a("code",[t._v("makeWebSocketService")]),t._v(".")]),t._v(" "),a("p",[t._v("The main differences between these and the methods from the built-in adapters is that they return one or several tapir "),a("code",[t._v("ServerEndpoint")]),t._v(",\nwhich you can then pass to a tapir interpreter. The returned "),a("code",[t._v("ServerEndpoint")]),t._v(" use "),a("code",[t._v("RIO[R, *]")]),t._v(" as an effect type, but you can easily transform it to another effect type. A helper "),a("code",[t._v("convertHttpEndpointToFuture")]),t._v(" allows converting the effect type to a scala "),a("code",[t._v("Future")]),t._v(" (this is used in the Akka, Pekko, and Play interpreters).")]),t._v(" "),a("h2",{attrs:{id:"high-performance-quickadapter"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#high-performance-quickadapter"}},[t._v("#")]),t._v(" High-performance "),a("code",[t._v("QuickAdapter")])]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("QuickAdapter")]),t._v(" requires minimal setup and uses "),a("a",{attrs:{href:"https://github.com/zio/zio-http",target:"_blank",rel:"noopener noreferrer"}},[t._v("zio-http"),a("OutboundLink")],1),t._v("\nand "),a("a",{attrs:{href:"https://github.com/plokhotnyuk/jsoniter-scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("jsoniter-scala"),a("OutboundLink")],1),t._v(" without tapir in order to provide the best possible performance.")]),t._v(" "),a("h3",{attrs:{id:"usage"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#usage"}},[t._v("#")]),t._v(" Usage")]),t._v(" "),a("p",[t._v("In order to use it, just add the following to your "),a("code",[t._v("build.sbt")]),t._v(" file (no other dependencies required!):")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("libraryDependencies "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-quick"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v("\n")])])]),a("p",[t._v("By adding "),a("code",[t._v("import caliban.quick._")]),t._v(", we expose a few convenient extension methods on our "),a("code",[t._v("GraphQL")]),t._v(" api.\nFor example, we can serve our GraphQL api with minimal setup via a single command:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:compile-only extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("quick"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\napi"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("runServer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n port "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("8080")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n apiPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/api/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n graphiqlPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/graphiql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n uploadPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/upload/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Optional, for enabling GraphQL uploads")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("Alternatively, you can also create a zio-http "),a("code",[t._v("Handler")]),t._v(" and manually compose it into an app:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:compile-only extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("quick"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n handlers "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("handlers\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Alternatively, without imported syntax:")]),t._v("\n handlers2 "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("QuickAdapter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("handlers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Creates a handler which serves the GraphiQL API from CDN")]),t._v("\n graphiql "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" GraphiQLHandler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("handler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("apiPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/api/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" graphiqlPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/graphiql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n app "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Routes"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Method"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ANY "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"api"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"graphql"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" handlers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Method"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("GET "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"graphiql"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" graphiql"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Method"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("POST "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"upload"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"graphql"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" handlers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("upload\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Add more routes, apply middleware, etc.")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" Server"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("serve"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("app"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("provide"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Server"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("defaultWithPort"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("8080")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h3",{attrs:{id:"customization"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#customization"}},[t._v("#")]),t._v(" Customization")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("QuickAdapter")]),t._v(" exposes the following methods that allow you to customize the server or apply middleware to the routes:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("configure")]),t._v(" which takes a "),a("code",[t._v("Configurator[R]")]),t._v(" "),a("RouterLink",{attrs:{to:"/docs/adapters.html#built-in-tapir-adapters"}},[t._v("similar to the tapir-based adapters")])],1),t._v(" "),a("li",[a("code",[t._v("handlers")]),t._v(" which returns a "),a("code",[t._v("QuickHandlers[R]")]),t._v(" which contains individual handlers to manually construct routes.\nNote that this handler is only for the api routes. To construct the graphiql handler use "),a("code",[t._v("caliban.GraphiQLHandler.handler")]),t._v(".")])]),t._v(" "),a("p",[t._v("For more info on customization and middleware, check out the "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/quick",target:"_blank",rel:"noopener noreferrer"}},[t._v("adapter examples"),a("OutboundLink")],1),t._v("!")])])}),[],!1,null,null,null);a.default=r.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/25.8e82221d.js b/docs/assets/js/25.8e82221d.js new file mode 100644 index 0000000000..6664c1145a --- /dev/null +++ b/docs/assets/js/25.8e82221d.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[25],{306:function(t,a,e){"use strict";e.r(a);var s=e(14),r=Object(s.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"http-adapters"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#http-adapters"}},[t._v("#")]),t._v(" Http Adapters")]),t._v(" "),a("p",[t._v('Once you have an interpreter able to execute GraphQL queries, you usually want to expose it using an HTTP API.\nCaliban comes with a few "ready-to-use" components (called "adapters") to expose your API with the most popular HTTP libraries.')]),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("`QuickAdapter`")]),t._v(" "),a("p",[t._v("Starting with v2.4.3, Caliban provides the opinionated "),a("RouterLink",{attrs:{to:"/docs/adapters.html#high-performance-quickadapter"}},[t._v("QuickAdapter")]),t._v("\nthat favours ease-of-use and performance at the expense of customizability.")],1),t._v(" "),a("p",[t._v("If you want the best possible performance, make sure to check it out!")])]),t._v(" "),a("h2",{attrs:{id:"built-in-tapir-adapters"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#built-in-tapir-adapters"}},[t._v("#")]),t._v(" Built-in tapir adapters")]),t._v(" "),a("p",[t._v("Under the hood, adapters use the "),a("a",{attrs:{href:"https://tapir.softwaremill.com/en/latest/",target:"_blank",rel:"noopener noreferrer"}},[t._v("tapir"),a("OutboundLink")],1),t._v(" library, so you can easily create a custom adapter with anything that tapir supports.")]),t._v(" "),a("p",[t._v("The following adapters are provided:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("Http4sAdapter")]),t._v(" exposes a route for http4s.")]),t._v(" "),a("li",[a("code",[t._v("QuickAdapter")]),t._v(" exposes a route for zio-http.")]),t._v(" "),a("li",[a("code",[t._v("PlayHttpAdapter")]),t._v(" exposes a route for play.")]),t._v(" "),a("li",[a("code",[t._v("AkkaHttpAdapter")]),t._v(" exposes a route for akka.")]),t._v(" "),a("li",[a("code",[t._v("PekkoHttpAdapter")]),t._v(" exposes a route for pekko.")])]),t._v(" "),a("p",[t._v("To use them, you first need to transform your "),a("code",[t._v("GraphQLInterpreter")]),t._v(" obtained from "),a("code",[t._v("api.interpreter")]),t._v(" into a new type of interpreter that supports the protocol you want to use.\nThere are 3 of them:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("HttpInterpreter")]),t._v(" follows the "),a("a",{attrs:{href:"https://graphql.org/learn/serving-over-http/#http-methods-headers-and-body",target:"_blank",rel:"noopener noreferrer"}},[t._v("standard GraphQL protocol"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("code",[t._v("HttpUploadInterpreter")]),t._v(" follows the "),a("a",{attrs:{href:"https://github.com/jaydenseric/graphql-multipart-request-spec",target:"_blank",rel:"noopener noreferrer"}},[t._v("GraphQL multipart request protocol"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("code",[t._v("WebSocketInterpreter")]),t._v(" follows the "),a("a",{attrs:{href:"https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md",target:"_blank",rel:"noopener noreferrer"}},[t._v("GraphQL WebSocket protocol"),a("OutboundLink")],1)])]),t._v(" "),a("p",[t._v("These interpreters expose 2 powerful methods:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("configure")]),t._v(" takes a "),a("code",[t._v("Configurator[R]")]),t._v(" which is an alias for "),a("code",[t._v("URIO[R & Scope, Unit]")]),t._v(".\nIt allows configuring the interpreter by running an effect that will run for each request and that can modify the configuration of the running fiber. Built-in configurators such as "),a("code",[t._v("Configurator.setSkipValidation")]),t._v(", "),a("code",[t._v("Configurator.setEnableIntrospection")]),t._v(" and "),a("code",[t._v("Configurator.setQueryExecution")]),t._v(" let you dynamically change the configuration of the interpreter.")]),t._v(" "),a("li",[a("code",[t._v("intercept")]),t._v(" takes an "),a("code",[t._v("Interceptor[-R1, +R]")]),t._v(" which is an alias for "),a("code",[t._v("ZLayer[R1 & ServerRequest, TapirResponse, R]")]),t._v(".\nIt is basically a more powerful version of "),a("code",[t._v("configure")]),t._v(" that gives you access to the incoming request ("),a("code",[t._v("ServerRequest")]),t._v(") and lets you modify the environment of the interpreter (from "),a("code",[t._v("R")]),t._v(" to "),a("code",[t._v("R1")]),t._v("). A typical use case would be to extract an authentication token from the request and eliminate the authentication requirement from the environment if the token is valid. See an example "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/blob/series/2.x/examples/src/main/scala/example/akkahttp/AuthExampleApp.scala#L51",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1),t._v(".")])]),t._v(" "),a("p",[t._v("In addition to that, the "),a("code",[t._v("WebSocketInterpreter")]),t._v(" constructor comes with 2 optional parameters:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("keepAliveInterval")]),t._v(" (default: empty) defines the interval for the server to send keep alive messages to the client")]),t._v(" "),a("li",[a("code",[t._v("webSocketHooks")]),t._v(" (default: empty) gives you some hooks around the WebSocket lifecycle (useful for authentication)")])]),t._v(" "),a("p",[t._v("Once your interpreter is correctly configured, you can use one of these 3 functions exposed by each built-in adapter:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("makeHttpService")]),t._v(" turns an "),a("code",[t._v("HttpInterpreter")]),t._v(" into a route for the corresponding library")]),t._v(" "),a("li",[a("code",[t._v("makeHttpUploadService")]),t._v(" turns an "),a("code",[t._v("HttpUploadInterpreter")]),t._v(" into a route for the corresponding library")]),t._v(" "),a("li",[a("code",[t._v("makeWebSocketService")]),t._v(" turns a "),a("code",[t._v("WebSocketInterpreter")]),t._v(" into a route for the corresponding library")])]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" graphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("AuthToken"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// turn our GraphQL interpreter into an HttpInterpreter")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" noAuthInterpreter"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" HttpInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("AuthToken"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" HttpInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("graphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// define authentication logic (from a ServerRequest, fail or build an AuthToken)")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" auth"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ZLayer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ServerRequest"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" TapirResponse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" AuthToken"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// pass our interceptor to eliminate the AuthToken requirement from the environment")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" authInterpreter"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" HttpUploadInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" httpInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("intercept"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("auth"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// get our route for Akka Http")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" route "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" AkkaHttpAdapter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("default"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("makeHttpService"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("authInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("Want to use something else? Check "),a("a",{attrs:{href:"#make-your-own-adapter"}},[t._v("make your own adapter section")]),t._v("!")]),t._v(" "),a("p",[t._v("Make sure to check the "),a("RouterLink",{attrs:{to:"/docs/examples.html"}},[t._v("examples")]),t._v(" to see the adapters in action.")],1),t._v(" "),a("h2",{attrs:{id:"json-handling"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#json-handling"}},[t._v("#")]),t._v(" Json handling")]),t._v(" "),a("p",[t._v("Caliban comes with JSON encoders and decoders for the following libraries:")]),t._v(" "),a("ul",[a("li",[t._v("circe")]),t._v(" "),a("li",[t._v("jsoniter-scala (JDK 11+ only)")]),t._v(" "),a("li",[t._v("play-json")]),t._v(" "),a("li",[t._v("zio-json")])]),t._v(" "),a("p",[t._v("Since v2.1.0, the adapters are not bound to a specific JSON handler and require the user to add the "),a("RouterLink",{attrs:{to:"/docs/#interop-with-3rd-party-libraries"}},[t._v("corresponding dependency")]),t._v(" in their project and import the implicits in scope when calling the "),a("code",[t._v("makeHttpService")]),t._v(" / "),a("code",[t._v("makeHttpUploadService")]),t._v(" / "),a("code",[t._v("makeWebSocketService")]),t._v(" methods.")],1),t._v(" "),a("p",[t._v("Let's say we want to use "),a("code",[t._v("http4s")]),t._v(" as the server implementation with "),a("code",[t._v("zio-json")]),t._v(" as the json handler. Defining the http4s route is as simple as:")]),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(" http4sRoute "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("json"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n Http4sAdapter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("makeHttpService"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("interpreter"),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("That's it! "),a("code",[t._v("http4sRoute")]),t._v(" is a valid http4s route ready to serve our API.")]),t._v(" "),a("p",[t._v("If you use another json library, you will need to create encoders and decoders for it (which is very simple, you can simply look at the existing ones).\nThe full list of JSON libraries supported by Tapir can be found "),a("a",{attrs:{href:"https://tapir.softwaremill.com/en/latest/endpoint/json.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1)]),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("Known issues: jsoniter-scala")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("makeHttpUploadService")]),t._v(" methods require an implicit of "),a("code",[t._v("JsonCodec[Map[String,Seq[String]]]")]),t._v(" in scope. Jsoniter does not provide\ncodecs for common types by default, which means the user needs to create one. To do so, add the "),a("code",[t._v("jsoniter-scala-macros")]),t._v(" dependency to your project and create one as:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("json"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("jsoniter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("com"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("github"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("plokhotnyuk"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("jsoniter_scala"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("core"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("com"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("github"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("plokhotnyuk"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("jsoniter_scala"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("macros"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" http4sRoute "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("json"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("jsoniter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" codec"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" JsonValueCodec"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Seq"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" JsonCodecMaker"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("make\n\n Http4sAdapter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("makeHttpUploadService"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("interpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"custom-block warning"},[a("p",{staticClass:"custom-block-title"},[t._v("WARNING")]),t._v(" "),a("p",[t._v("To maximize performance, the "),a("strong",[t._v("jsoniter")]),t._v(" codec implementation is stack-recursive. To prevent stack overflow errors, it has a "),a("strong",[t._v("maximum depth limit of 512")]),t._v(".")]),t._v(" "),a("p",[t._v("If your schema contains recursive types and want to use the jsoniter codecs, make sure to also limit the maximum query depth using\nthe "),a("RouterLink",{attrs:{to:"/docs/middleware.html#pre-defined-wrappers"}},[t._v("maxDepth wrapper")]),t._v(".")],1)])]),t._v(" "),a("h2",{attrs:{id:"make-your-own-adapter"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#make-your-own-adapter"}},[t._v("#")]),t._v(" Make your own adapter")]),t._v(" "),a("p",[t._v("All existing adapters are actually using a common adapter under the hood, called "),a("code",[t._v("TapirAdapter")]),t._v(".")]),t._v(" "),a("p",[t._v("This adapter, available in the "),a("code",[t._v("caliban-tapir")]),t._v(" dependency which has the same 3 methods "),a("code",[t._v("makeHttpService")]),t._v(", "),a("code",[t._v("makeHttpUploadService")]),t._v(" and "),a("code",[t._v("makeWebSocketService")]),t._v(".")]),t._v(" "),a("p",[t._v("The main differences between these and the methods from the built-in adapters is that they return one or several tapir "),a("code",[t._v("ServerEndpoint")]),t._v(",\nwhich you can then pass to a tapir interpreter. The returned "),a("code",[t._v("ServerEndpoint")]),t._v(" use "),a("code",[t._v("RIO[R, *]")]),t._v(" as an effect type, but you can easily transform it to another effect type. A helper "),a("code",[t._v("convertHttpEndpointToFuture")]),t._v(" allows converting the effect type to a scala "),a("code",[t._v("Future")]),t._v(" (this is used in the Akka, Pekko, and Play interpreters).")]),t._v(" "),a("h2",{attrs:{id:"high-performance-quickadapter"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#high-performance-quickadapter"}},[t._v("#")]),t._v(" High-performance "),a("code",[t._v("QuickAdapter")])]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("QuickAdapter")]),t._v(" requires minimal setup and uses "),a("a",{attrs:{href:"https://github.com/zio/zio-http",target:"_blank",rel:"noopener noreferrer"}},[t._v("zio-http"),a("OutboundLink")],1),t._v("\nand "),a("a",{attrs:{href:"https://github.com/plokhotnyuk/jsoniter-scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("jsoniter-scala"),a("OutboundLink")],1),t._v(" without tapir in order to provide the best possible performance.")]),t._v(" "),a("h3",{attrs:{id:"usage"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#usage"}},[t._v("#")]),t._v(" Usage")]),t._v(" "),a("p",[t._v("In order to use it, just add the following to your "),a("code",[t._v("build.sbt")]),t._v(" file (no other dependencies required!):")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("libraryDependencies "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-quick"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v("\n")])])]),a("p",[t._v("By adding "),a("code",[t._v("import caliban.quick._")]),t._v(", we expose a few convenient extension methods on our "),a("code",[t._v("GraphQL")]),t._v(" api.\nFor example, we can serve our GraphQL api with minimal setup via a single command:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:compile-only extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("quick"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\napi"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("unsafe"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("runServer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n port "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("8080")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n apiPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/api/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n graphiqlPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/graphiql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n uploadPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/upload/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// optional, for enabling GraphQL uploads")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("Alternatively, you can also create a zio-http "),a("code",[t._v("Handler")]),t._v(" and manually compose it into an app:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:compile-only extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("quick"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n handlers "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("handlers\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Alternatively, without imported syntax:")]),t._v("\n handlers2 "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("QuickAdapter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("handlers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Creates a handler which serves the GraphiQL API from CDN")]),t._v("\n graphiql "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" GraphiQLHandler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("handler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("apiPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/api/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" graphiqlPath "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/graphiql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n app "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Routes"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Method"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ANY "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"api"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"graphql"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" handlers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Method"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("GET "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"graphiql"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" graphiql"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Method"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("POST "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"upload"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"graphql"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" handlers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("upload\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Add more routes, apply middleware, etc.")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" Server"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("serve"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("app"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("provide"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Server"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("defaultWithPort"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("8080")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h3",{attrs:{id:"customization"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#customization"}},[t._v("#")]),t._v(" Customization")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("QuickAdapter")]),t._v(" exposes the following methods that allow you to customize the server or apply middleware to the routes:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("configure")]),t._v(" which takes a "),a("code",[t._v("Configurator[R]")]),t._v(" "),a("RouterLink",{attrs:{to:"/docs/adapters.html#built-in-tapir-adapters"}},[t._v("similar to the tapir-based adapters")])],1),t._v(" "),a("li",[a("code",[t._v("handlers")]),t._v(" which returns a "),a("code",[t._v("QuickHandlers[R]")]),t._v(" which contains individual handlers to manually construct routes.\nNote that this handler is only for the api routes. To construct the graphiql handler use "),a("code",[t._v("caliban.GraphiQLHandler.handler")]),t._v(".")])]),t._v(" "),a("p",[t._v("For more info on customization and middleware, check out the "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/quick",target:"_blank",rel:"noopener noreferrer"}},[t._v("adapter examples"),a("OutboundLink")],1),t._v("!")])])}),[],!1,null,null,null);a.default=r.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/28.755a8b70.js b/docs/assets/js/28.755a8b70.js new file mode 100644 index 0000000000..ab8c144b35 --- /dev/null +++ b/docs/assets/js/28.755a8b70.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[28],{309:function(e,t,r){"use strict";r.r(t);var a=r(14),n=Object(a.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"examples"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#examples"}},[e._v("#")]),e._v(" Examples")]),e._v(" "),t("p",[e._v("The "),t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/",target:"_blank",rel:"noopener noreferrer"}},[e._v("examples"),t("OutboundLink")],1),e._v(" project in Github contains various examples:")]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/quick",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with the high-performance HTTP adapter"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/http4s",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with http4s"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/akkahttp",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with Akka HTTP"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/pekkohttp",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with Pekko HTTP"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/play",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with play"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("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"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/ziohttp",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with zio-http"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/client",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL Client usage"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/client-laminext/src/test/scala/caliban/client/laminext",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL Client integration with Laminext"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/optimizations",target:"_blank",rel:"noopener noreferrer"}},[e._v("Optimization with ZQuery"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/interop/cats",target:"_blank",rel:"noopener noreferrer"}},[e._v("Interop with Cats Effect"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/tapir",target:"_blank",rel:"noopener noreferrer"}},[e._v("Interop with Tapir"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/federation",target:"_blank",rel:"noopener noreferrer"}},[e._v("Apollo Federation usage"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/stitching",target:"_blank",rel:"noopener noreferrer"}},[e._v("Schema Stitching usage"),t("OutboundLink")],1)])]),e._v(" "),t("h4",{attrs:{id:"available-only-with-cats-effect-2-x"}},[t("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(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/interop/monix",target:"_blank",rel:"noopener noreferrer"}},[e._v("Interop with Monix"),t("OutboundLink")],1)])]),e._v(" "),t("p",[e._v("You may also check out "),t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban-blog-series",target:"_blank",rel:"noopener noreferrer"}},[e._v("the repository"),t("OutboundLink")],1),e._v(" accompanying my "),t("a",{attrs:{href:"https://medium.com/@ghostdogpr/graphql-in-scala-with-caliban-part-1-8ceb6099c3c2",target:"_blank",rel:"noopener noreferrer"}},[e._v("blog series"),t("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/28.d0ed8364.js b/docs/assets/js/28.d0ed8364.js deleted file mode 100644 index e157ec58e6..0000000000 --- a/docs/assets/js/28.d0ed8364.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[28],{309:function(e,t,r){"use strict";r.r(t);var a=r(14),n=Object(a.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"examples"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#examples"}},[e._v("#")]),e._v(" Examples")]),e._v(" "),t("p",[e._v("The "),t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/",target:"_blank",rel:"noopener noreferrer"}},[e._v("examples"),t("OutboundLink")],1),e._v(" project in Github contains various examples:")]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/quick",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with the high-performance HTTP adapter"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/http4s",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with http4s"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/akkahttp",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with Akka HTTP"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/play",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with play"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("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"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/ziohttp",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL API exposed with zio-http"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/client",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL Client usage"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/client-laminext/src/test/scala/caliban/client/laminext",target:"_blank",rel:"noopener noreferrer"}},[e._v("GraphQL Client integration with Laminext"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/optimizations",target:"_blank",rel:"noopener noreferrer"}},[e._v("Optimization with ZQuery"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/interop/cats",target:"_blank",rel:"noopener noreferrer"}},[e._v("Interop with Cats Effect"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/tapir",target:"_blank",rel:"noopener noreferrer"}},[e._v("Interop with Tapir"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/federation",target:"_blank",rel:"noopener noreferrer"}},[e._v("Apollo Federation usage"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/stitching",target:"_blank",rel:"noopener noreferrer"}},[e._v("Schema Stitching usage"),t("OutboundLink")],1)])]),e._v(" "),t("h4",{attrs:{id:"available-only-with-cats-effect-2-x"}},[t("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(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/interop/monix",target:"_blank",rel:"noopener noreferrer"}},[e._v("Interop with Monix"),t("OutboundLink")],1)])]),e._v(" "),t("p",[e._v("You may also check out "),t("a",{attrs:{href:"https://github.com/ghostdogpr/caliban-blog-series",target:"_blank",rel:"noopener noreferrer"}},[e._v("the repository"),t("OutboundLink")],1),e._v(" accompanying my "),t("a",{attrs:{href:"https://medium.com/@ghostdogpr/graphql-in-scala-with-caliban-part-1-8ceb6099c3c2",target:"_blank",rel:"noopener noreferrer"}},[e._v("blog series"),t("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/30.cc13c839.js b/docs/assets/js/30.cc13c839.js new file mode 100644 index 0000000000..b638a3a69f --- /dev/null +++ b/docs/assets/js/30.cc13c839.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[30],{311:function(t,a,s){"use strict";s.r(a);var n=s(14),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"interop-with-other-libraries"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#interop-with-other-libraries"}},[t._v("#")]),t._v(" Interop with other libraries")]),t._v(" "),a("p",[t._v("If you prefer using "),a("a",{attrs:{href:"https://github.com/typelevel/cats-effect",target:"_blank",rel:"noopener noreferrer"}},[t._v("Cats Effect"),a("OutboundLink")],1),t._v(" or "),a("a",{attrs:{href:"https://github.com/monix/monix",target:"_blank",rel:"noopener noreferrer"}},[t._v("Monix"),a("OutboundLink")],1),t._v(" rather than ZIO, you can use the respective "),a("code",[t._v("caliban-cats")]),t._v(" and "),a("code",[t._v("caliban-monix")]),t._v(" modules.")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("caliban-tapir")]),t._v(" module allows converting your "),a("a",{attrs:{href:"https://github.com/softwaremill/tapir",target:"_blank",rel:"noopener noreferrer"}},[t._v("Tapir"),a("OutboundLink")],1),t._v(" endpoints into a GraphQL API.")]),t._v(" "),a("h2",{attrs:{id:"cats-effect"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#cats-effect"}},[t._v("#")]),t._v(" Cats Effect")]),t._v(" "),a("p",[t._v("You first need to import "),a("code",[t._v("caliban.interop.cats.implicits._")]),t._v(" and have an implicit "),a("code",[t._v("zio.Runtime")]),t._v(" in scope. Then a few helpers are available:")]),t._v(" "),a("ul",[a("li",[t._v("the "),a("code",[t._v("GraphQL")]),t._v(" object is enriched with "),a("code",[t._v("interpreterAsync")]),t._v(", a variant of "),a("code",[t._v("interpreter")]),t._v(" that return an "),a("code",[t._v("F[_]: Async")]),t._v(" instead of a "),a("code",[t._v("ZIO")]),t._v(".")]),t._v(" "),a("li",[t._v("the "),a("code",[t._v("GraphQLInterpreter")]),t._v(" object is enriched with "),a("code",[t._v("executeAsync")]),t._v(" and "),a("code",[t._v("checkAsync")]),t._v(", variants of "),a("code",[t._v("execute")]),t._v(" and "),a("code",[t._v("check")]),t._v(" that return an "),a("code",[t._v("F[_]: Async")]),t._v(" instead of a "),a("code",[t._v("ZIO")]),t._v(".")]),t._v(" "),a("li",[t._v("the "),a("code",[t._v("Http4sAdapter")]),t._v(" also has a helper to turn endpoints into cats-effect named "),a("code",[t._v("convertHttpEndpointToF")]),t._v(".")])]),t._v(" "),a("p",[t._v("In addition to that, a "),a("code",[t._v("Schema")]),t._v(" for any "),a("code",[t._v("F[_]: Async: Dispatcher")]),t._v(" is provided. That means you can include fields with results wrapped in "),a("code",[t._v("F")]),t._v(" in your queries, mutations or subscriptions.")]),t._v(" "),a("p",[t._v("There are two type classes responsible for the conversion between effects: "),a("code",[t._v("caliban.interop.cats.ToEffect")]),t._v(" and "),a("code",[t._v("caliban.interop.cats.FromEffect")]),t._v(".\nThe instances are derived implicitly when "),a("code",[t._v("Async[F]")]),t._v(", "),a("code",[t._v("Dispatcher[F]")]),t._v(", and "),a("code",[t._v("Runtime[R]")]),t._v(" are available in the implicit scope.")]),t._v(" "),a("h4",{attrs:{id:"interop-with-cats-effect-io"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#interop-with-cats-effect-io"}},[t._v("#")]),t._v(" Interop with cats.effect.IO")]),t._v(" "),a("p",[t._v("The following example shows how to create an interpreter and run a query while only using Cats IO.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("implicits"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("effect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" ExitCode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IOApp "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),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("std"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Dispatcher\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Runtime\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" ExampleCatsInterop "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" IOApp "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" zioRuntime "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Runtime"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("default\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("numbers"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" randomNumber"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" queries "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("scala"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("util"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Random"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nextInt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" query "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token triple-quoted-string string"}},[t._v('"""\n {\n numbers\n randomNumber\n }"""')]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" run"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ExitCode"),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 Dispatcher"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parallel"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("use "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" dispatcher "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// required for a derivation of the schema")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\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 interpreter "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interpreterAsync"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n result "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" interpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("executeAsync"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("println"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" ExitCode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Success\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("You can find this example within the "),a("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"),a("OutboundLink")],1),t._v(" project.")]),t._v(" "),a("h4",{attrs:{id:"interop-with-contextual-effect-e-g-kleisli"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#interop-with-contextual-effect-e-g-kleisli"}},[t._v("#")]),t._v(" Interop with contextual effect (e.g. Kleisli)")]),t._v(" "),a("p",[a("code",[t._v("CatsInterop")]),t._v(" (the combination of "),a("code",[t._v("ToEffect")]),t._v(" and "),a("code",[t._v("FromEffect")]),t._v(") allows sharing a context between cats-effect and ZIO:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:compile-only extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Kleisli\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),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("IO\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),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("std"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Dispatcher\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("CatsInterop\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("RIO\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Context\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Effect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Kleisli"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" dispatcher"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Dispatcher"),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(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" runtime"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Runtime"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" interop"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CatsInterop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Contextual"),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(" Context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" CatsInterop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("contextual"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dispatcher"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" rio"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" RIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" ce"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Kleisli"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" fromRIO"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Kleisli"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" interop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toEffect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("rio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" fromCE"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" RIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" interop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromEffect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ce"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("implicits"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("GenericSchema\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Kleisli\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("effect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" Async"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ExitCode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IOApp "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),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("std"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Dispatcher\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),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("std"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Console\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("syntax"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("flatMap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("syntax"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("functor"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mtl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Local\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mtl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("syntax"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("local"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" Runtime"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ZEnvironment "),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(" Simple "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" IOApp "),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("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("numbers"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" randomNumber"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" query "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token triple-quoted-string string"}},[t._v('"""\n {\n numbers\n randomNumber\n }"""')]),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(" TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" TraceLocal"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Local"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Logger"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),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(" info"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("message"),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(" F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" program"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Async"),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 keyword"}},[t._v("implicit")]),t._v("\n logger"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Logger"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n local"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Local"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n inject"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" InjectEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n runtime"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Runtime"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ExitCode"),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 Dispatcher"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parallel"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("use "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" dispatcher "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" interop"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CatsInterop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Contextual"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" CatsInterop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("contextual"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dispatcher"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// required for a derivation of the schema")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" genRandomNumber "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" logger"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("info"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Generating number"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>")]),t._v(" Async"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("delay"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("scala"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("util"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Random"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nextInt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" queries "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n genRandomNumber"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("scope"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"gen-number"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GenericSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" GenericSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n interpreter "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interpreterAsync"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n result "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" interpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("executeAsync"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" logger"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("info"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),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 "),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(" ExitCode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Success\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" run"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ExitCode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Effect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Kleisli"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" root "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"root"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" runtime "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Runtime"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("default"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("withEnvironment"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ZEnvironment"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("root"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" logger "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" Logger"),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(" "),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(" info"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("message"),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(" Effect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n traceId "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" Local"),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(" TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ask"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" Console"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Effect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("println"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("message")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v(" - ")]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("traceId")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n program"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Effect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("run"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("root"),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("There is another real world "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/blob/master/examples/src/main/scala/example/http4s/AuthExampleAppF.scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("example"),a("OutboundLink")],1),t._v(", that shows how to share auth info between cats-effect and ZIO.")]),t._v(" "),a("h2",{attrs:{id:"monix-only-with-cats-effect-2-x"}},[a("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(" "),a("p",[t._v("You first need to import "),a("code",[t._v("caliban.interop.monix.implicits._")]),t._v(" and have an implicit "),a("code",[t._v("zio.Runtime")]),t._v(" in scope. Then a few helpers are available:")]),t._v(" "),a("ul",[a("li",[t._v("the "),a("code",[t._v("GraphQL")]),t._v(" object is enriched with "),a("code",[t._v("interpreterAsync")]),t._v(", a variant of "),a("code",[t._v("interpreter")]),t._v(" that return a Monix "),a("code",[t._v("Task")]),t._v(" instead of a "),a("code",[t._v("ZIO")]),t._v(".")]),t._v(" "),a("li",[t._v("the "),a("code",[t._v("GraphQLInterpreter")]),t._v(" object is enriched with "),a("code",[t._v("executeAsync")]),t._v(" and "),a("code",[t._v("checkAsync")]),t._v(", variants of "),a("code",[t._v("execute")]),t._v(" and "),a("code",[t._v("check")]),t._v(" that return a Monix "),a("code",[t._v("Task")]),t._v(" instead of a "),a("code",[t._v("ZIO")]),t._v(".")])]),t._v(" "),a("p",[t._v("In addition to that, a "),a("code",[t._v("Schema")]),t._v(" for any Monix "),a("code",[t._v("Task")]),t._v(" as well as "),a("code",[t._v("Observable")]),t._v(" is provided.")]),t._v(" "),a("p",[t._v("The following example shows how to create an interpreter and run a query while only using Monix Task.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("monix"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("implicits"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),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("ExitCode\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("monix"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("eval"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" Task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" TaskApp "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("monix"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("execution"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Scheduler\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Runtime\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" ExampleMonixInterop "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" TaskApp "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" zioRuntime "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Runtime"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("default\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(" monixScheduler"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Scheduler "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" scheduler\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("numbers"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" randomNumber"),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("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" queries "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("eval"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("scala"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("util"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Random"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nextInt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" query "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token triple-quoted-string string"}},[t._v('"""\n {\n numbers\n randomNumber\n }"""')]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" run"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),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("ExitCode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n interpreter "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interpreterAsync\n result "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" interpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("executeAsync"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" Task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("eval"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("println"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" ExitCode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Success\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("You can find this example within the "),a("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"),a("OutboundLink")],1),t._v(" project.")]),t._v(" "),a("h2",{attrs:{id:"tapir"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#tapir"}},[t._v("#")]),t._v(" Tapir")]),t._v(" "),a("p",[t._v("After adding the "),a("code",[t._v("caliban-tapir")]),t._v(" dependency to your build, adding "),a("code",[t._v("import caliban.interop.tapir._")]),t._v(" to your code will introduce an extension method called "),a("code",[t._v("toGraphQL")]),t._v(" on Tapir's "),a("code",[t._v("Endpoint")]),t._v(" and "),a("code",[t._v("ServerEndpoint")]),t._v(".\nThis method will convert your endpoint into a "),a("code",[t._v("GraphQL")]),t._v(" object that you can then combine and expose.")]),t._v(" "),a("p",[t._v("The conversion rules are the following:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("GET")]),t._v(" endpoints are turned into Queries")]),t._v(" "),a("li",[a("code",[t._v("PUT")]),t._v(", "),a("code",[t._v("POST")]),t._v(" and "),a("code",[t._v("DELETE")]),t._v(" endpoints are turned into Mutations")]),t._v(" "),a("li",[t._v("fixed query paths are used to name GraphQL fields (e.g. an endpoint "),a("code",[t._v("/book/add")]),t._v(" will give a GraphQL field named "),a("code",[t._v("bookAdd")]),t._v(")")]),t._v(" "),a("li",[t._v("query parameters, headers, cookies and request body are used as GraphQL arguments")]),t._v(" "),a("li",[t._v("there should be an implicit "),a("code",[t._v("Schema")]),t._v(" for both the input and the output types and an implicit "),a("code",[t._v("ArgBuilder")]),t._v(" for the input type (see the "),a("RouterLink",{attrs:{to:"/docs/schema.html"}},[t._v("dedicated docs")]),t._v(")")],1)]),t._v(" "),a("p",[t._v("Let's look at an example. Imagine we have the following Tapir endpoint:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("io"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("circe"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("generic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("generic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("json"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("circe"),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(" Book"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("title"),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(" year"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" addBook"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" PublicEndpoint"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Book"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n infallibleEndpoint\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("post\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("in"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"books"')]),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("in"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"add"')]),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("in"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n jsonBody"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Book"),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("description"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"The book to add"')]),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("example"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Book"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Pride and Prejudice"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1813")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("in"),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 builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"X-Auth-Token"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("description"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"The token is 'secret'\"")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("And a possible implementation:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("UIO\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" bookAddLogic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("book"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Book"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" token"),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(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),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("Just like you can create an http4s route by calling "),a("code",[t._v("toRoute")]),t._v(" and passing an implementation, call "),a("code",[t._v("toGraphQL")]),t._v(" to create a GraphQL API:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_ "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// summons 'toGraphQL' extension")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" addBook"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toGraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("bookAddLogic _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tupled"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("That's it! You can combine multiple "),a("code",[t._v("GraphQL")]),t._v(" objects using "),a("code",[t._v("|+|")]),t._v(" and expose the result using one of Caliban's adapters.")]),t._v(" "),a("p",[t._v("If you want to reuse "),a("code",[t._v("bookAddLogic")]),t._v(" for both GraphQL and regular HTTP, you can turn your "),a("code",[t._v("Endpoint")]),t._v(" into a "),a("code",[t._v("ServerEndpoint")]),t._v(" by calling "),a("code",[t._v(".serverLogicSuccess")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("server"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ServerEndpoint\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" addBookEndpoint"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ServerEndpoint"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Full"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Book"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" UIO"),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 addBook"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("serverLogicSuccess"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("book"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" token"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" bookAddLogic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("book"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" token"),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("p",[t._v("This can then be used to generate both an HTTP route (e.g. "),a("code",[t._v("toRoutes")]),t._v(" with http4s) and a GraphQL API ("),a("code",[t._v(".toGraphQL")]),t._v(").")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent:nest extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" addBookEndpoint"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toGraphQL\n")])])]),a("p",[t._v("You can find a "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/tapir",target:"_blank",rel:"noopener noreferrer"}},[t._v("full example"),a("OutboundLink")],1),t._v(" on github.")]),t._v(" "),a("h3",{attrs:{id:"graphql-restrictions"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#graphql-restrictions"}},[t._v("#")]),t._v(" GraphQL restrictions")]),t._v(" "),a("p",[a("a",{attrs:{href:"https://spec.graphql.org/June2018/#sec-Operation-Name-Uniqueness",target:"_blank",rel:"noopener noreferrer"}},[t._v("GraphQL spec"),a("OutboundLink")],1),t._v(" requires unique naming for all operations.")]),t._v(" "),a("p",[t._v("To customize the "),a("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"),a("OutboundLink")],1),t._v(" of an operation use "),a("code",[t._v("EndpointInfo.name")])]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("endpoint\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"overrideName"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/30.fbe96632.js b/docs/assets/js/30.fbe96632.js deleted file mode 100644 index 50d2848fd1..0000000000 --- a/docs/assets/js/30.fbe96632.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[30],{311:function(t,a,s){"use strict";s.r(a);var n=s(14),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"interop"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#interop"}},[t._v("#")]),t._v(" Interop")]),t._v(" "),a("p",[t._v("If you prefer using "),a("a",{attrs:{href:"https://github.com/typelevel/cats-effect",target:"_blank",rel:"noopener noreferrer"}},[t._v("Cats Effect"),a("OutboundLink")],1),t._v(" or "),a("a",{attrs:{href:"https://github.com/monix/monix",target:"_blank",rel:"noopener noreferrer"}},[t._v("Monix"),a("OutboundLink")],1),t._v(" rather than ZIO, you can use the respective "),a("code",[t._v("caliban-cats")]),t._v(" and "),a("code",[t._v("caliban-monix")]),t._v(" modules.")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("caliban-tapir")]),t._v(" module allows converting your "),a("a",{attrs:{href:"https://github.com/softwaremill/tapir",target:"_blank",rel:"noopener noreferrer"}},[t._v("Tapir"),a("OutboundLink")],1),t._v(" endpoints into a GraphQL API.")]),t._v(" "),a("h2",{attrs:{id:"cats-effect"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#cats-effect"}},[t._v("#")]),t._v(" Cats Effect")]),t._v(" "),a("p",[t._v("You first need to import "),a("code",[t._v("caliban.interop.cats.implicits._")]),t._v(" and have an implicit "),a("code",[t._v("zio.Runtime")]),t._v(" in scope. Then a few helpers are available:")]),t._v(" "),a("ul",[a("li",[t._v("the "),a("code",[t._v("GraphQL")]),t._v(" object is enriched with "),a("code",[t._v("interpreterAsync")]),t._v(", a variant of "),a("code",[t._v("interpreter")]),t._v(" that return an "),a("code",[t._v("F[_]: Async")]),t._v(" instead of a "),a("code",[t._v("ZIO")]),t._v(".")]),t._v(" "),a("li",[t._v("the "),a("code",[t._v("GraphQLInterpreter")]),t._v(" object is enriched with "),a("code",[t._v("executeAsync")]),t._v(" and "),a("code",[t._v("checkAsync")]),t._v(", variants of "),a("code",[t._v("execute")]),t._v(" and "),a("code",[t._v("check")]),t._v(" that return an "),a("code",[t._v("F[_]: Async")]),t._v(" instead of a "),a("code",[t._v("ZIO")]),t._v(".")]),t._v(" "),a("li",[t._v("the "),a("code",[t._v("Http4sAdapter")]),t._v(" also has a helper to turn endpoints into cats-effect named "),a("code",[t._v("convertHttpEndpointToF")]),t._v(".")])]),t._v(" "),a("p",[t._v("In addition to that, a "),a("code",[t._v("Schema")]),t._v(" for any "),a("code",[t._v("F[_]: Async: Dispatcher")]),t._v(" is provided. That means you can include fields with results wrapped in "),a("code",[t._v("F")]),t._v(" in your queries, mutations or subscriptions.")]),t._v(" "),a("p",[t._v("There are two type classes responsible for the conversion between effects: "),a("code",[t._v("caliban.interop.cats.ToEffect")]),t._v(" and "),a("code",[t._v("caliban.interop.cats.FromEffect")]),t._v(".\nThe instances are derived implicitly when "),a("code",[t._v("Async[F]")]),t._v(", "),a("code",[t._v("Dispatcher[F]")]),t._v(", and "),a("code",[t._v("Runtime[R]")]),t._v(" are available in the implicit scope.")]),t._v(" "),a("h4",{attrs:{id:"interop-with-cats-effect-io"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#interop-with-cats-effect-io"}},[t._v("#")]),t._v(" Interop with cats.effect.IO")]),t._v(" "),a("p",[t._v("The following example shows how to create an interpreter and run a query while only using Cats IO.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("implicits"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("effect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" ExitCode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IOApp "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),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("std"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Dispatcher\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Runtime\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" ExampleCatsInterop "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" IOApp "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" zioRuntime "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Runtime"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("default\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("numbers"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" randomNumber"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" queries "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("scala"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("util"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Random"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nextInt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" query "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token triple-quoted-string string"}},[t._v('"""\n {\n numbers\n randomNumber\n }"""')]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" run"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ExitCode"),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 Dispatcher"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parallel"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("use "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" dispatcher "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// required for a derivation of the schema")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\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 interpreter "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interpreterAsync"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n result "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" interpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("executeAsync"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("println"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" ExitCode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Success\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("You can find this example within the "),a("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"),a("OutboundLink")],1),t._v(" project.")]),t._v(" "),a("h4",{attrs:{id:"interop-with-contextual-effect-e-g-kleisli"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#interop-with-contextual-effect-e-g-kleisli"}},[t._v("#")]),t._v(" Interop with contextual effect (e.g. Kleisli)")]),t._v(" "),a("p",[a("code",[t._v("CatsInterop")]),t._v(" (the combination of "),a("code",[t._v("ToEffect")]),t._v(" and "),a("code",[t._v("FromEffect")]),t._v(") allows sharing a context between cats-effect and ZIO:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:compile-only extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Kleisli\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),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("IO\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),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("std"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Dispatcher\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("CatsInterop\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("RIO\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Context\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Effect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Kleisli"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" dispatcher"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Dispatcher"),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(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" runtime"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Runtime"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" interop"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CatsInterop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Contextual"),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(" Context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" CatsInterop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("contextual"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dispatcher"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" rio"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" RIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" ce"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Kleisli"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" fromRIO"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Kleisli"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" interop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toEffect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("rio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" fromCE"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" RIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" interop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromEffect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ce"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("implicits"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("GenericSchema\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Kleisli\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("effect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" Async"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ExitCode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IOApp "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),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("std"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Dispatcher\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),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("std"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Console\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("syntax"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("flatMap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("syntax"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("functor"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mtl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Local\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mtl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("syntax"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("local"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" Runtime"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ZEnvironment "),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(" Simple "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" IOApp "),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("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("numbers"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" randomNumber"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" query "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token triple-quoted-string string"}},[t._v('"""\n {\n numbers\n randomNumber\n }"""')]),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(" TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" TraceLocal"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Local"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Logger"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),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(" info"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("message"),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(" F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" program"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Async"),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 keyword"}},[t._v("implicit")]),t._v("\n logger"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Logger"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n local"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Local"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n inject"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" InjectEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n runtime"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Runtime"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ExitCode"),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 Dispatcher"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parallel"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("use "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" dispatcher "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" interop"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CatsInterop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Contextual"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" CatsInterop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("contextual"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dispatcher"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// required for a derivation of the schema")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" genRandomNumber "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" logger"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("info"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Generating number"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>")]),t._v(" Async"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("delay"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("scala"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("util"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Random"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nextInt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" queries "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n genRandomNumber"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("scope"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"gen-number"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GenericSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" GenericSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n interpreter "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interpreterAsync"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n result "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" interpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("executeAsync"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("F"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" logger"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("info"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),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 "),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(" ExitCode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Success\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" run"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ExitCode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Effect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Kleisli"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" root "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"root"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" runtime "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Runtime"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("default"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("withEnvironment"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ZEnvironment"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("root"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" logger "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" Logger"),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(" "),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(" info"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("message"),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(" Effect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n traceId "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" Local"),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(" TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ask"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("TraceId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" Console"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Effect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("println"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("message")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v(" - ")]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("traceId")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n program"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Effect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("run"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("root"),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("There is another real world "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/blob/master/examples/src/main/scala/example/http4s/AuthExampleAppF.scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("example"),a("OutboundLink")],1),t._v(", that shows how to share auth info between cats-effect and ZIO.")]),t._v(" "),a("h2",{attrs:{id:"monix-only-with-cats-effect-2-x"}},[a("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(" "),a("p",[t._v("You first need to import "),a("code",[t._v("caliban.interop.monix.implicits._")]),t._v(" and have an implicit "),a("code",[t._v("zio.Runtime")]),t._v(" in scope. Then a few helpers are available:")]),t._v(" "),a("ul",[a("li",[t._v("the "),a("code",[t._v("GraphQL")]),t._v(" object is enriched with "),a("code",[t._v("interpreterAsync")]),t._v(", a variant of "),a("code",[t._v("interpreter")]),t._v(" that return a Monix "),a("code",[t._v("Task")]),t._v(" instead of a "),a("code",[t._v("ZIO")]),t._v(".")]),t._v(" "),a("li",[t._v("the "),a("code",[t._v("GraphQLInterpreter")]),t._v(" object is enriched with "),a("code",[t._v("executeAsync")]),t._v(" and "),a("code",[t._v("checkAsync")]),t._v(", variants of "),a("code",[t._v("execute")]),t._v(" and "),a("code",[t._v("check")]),t._v(" that return a Monix "),a("code",[t._v("Task")]),t._v(" instead of a "),a("code",[t._v("ZIO")]),t._v(".")])]),t._v(" "),a("p",[t._v("In addition to that, a "),a("code",[t._v("Schema")]),t._v(" for any Monix "),a("code",[t._v("Task")]),t._v(" as well as "),a("code",[t._v("Observable")]),t._v(" is provided.")]),t._v(" "),a("p",[t._v("The following example shows how to create an interpreter and run a query while only using Monix Task.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("monix"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("implicits"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("cats"),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("ExitCode\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("monix"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("eval"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" Task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" TaskApp "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("monix"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("execution"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Scheduler\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Runtime\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" ExampleMonixInterop "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" TaskApp "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" zioRuntime "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Runtime"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("default\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(" monixScheduler"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Scheduler "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" scheduler\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("numbers"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" randomNumber"),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("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" queries "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("eval"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("scala"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("util"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Random"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nextInt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" query "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token triple-quoted-string string"}},[t._v('"""\n {\n numbers\n randomNumber\n }"""')]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" run"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),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("ExitCode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n interpreter "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interpreterAsync\n result "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" interpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("executeAsync"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" Task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("eval"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("println"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" ExitCode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Success\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("You can find this example within the "),a("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"),a("OutboundLink")],1),t._v(" project.")]),t._v(" "),a("h2",{attrs:{id:"tapir"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#tapir"}},[t._v("#")]),t._v(" Tapir")]),t._v(" "),a("p",[t._v("After adding the "),a("code",[t._v("caliban-tapir")]),t._v(" dependency to your build, adding "),a("code",[t._v("import caliban.interop.tapir._")]),t._v(" to your code will introduce an extension method called "),a("code",[t._v("toGraphQL")]),t._v(" on Tapir's "),a("code",[t._v("Endpoint")]),t._v(" and "),a("code",[t._v("ServerEndpoint")]),t._v(".\nThis method will convert your endpoint into a "),a("code",[t._v("GraphQL")]),t._v(" object that you can then combine and expose.")]),t._v(" "),a("p",[t._v("The conversion rules are the following:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("GET")]),t._v(" endpoints are turned into Queries")]),t._v(" "),a("li",[a("code",[t._v("PUT")]),t._v(", "),a("code",[t._v("POST")]),t._v(" and "),a("code",[t._v("DELETE")]),t._v(" endpoints are turned into Mutations")]),t._v(" "),a("li",[t._v("fixed query paths are used to name GraphQL fields (e.g. an endpoint "),a("code",[t._v("/book/add")]),t._v(" will give a GraphQL field named "),a("code",[t._v("bookAdd")]),t._v(")")]),t._v(" "),a("li",[t._v("query parameters, headers, cookies and request body are used as GraphQL arguments")]),t._v(" "),a("li",[t._v("there should be an implicit "),a("code",[t._v("Schema")]),t._v(" for both the input and the output types and an implicit "),a("code",[t._v("ArgBuilder")]),t._v(" for the input type (see the "),a("RouterLink",{attrs:{to:"/docs/schema.html"}},[t._v("dedicated docs")]),t._v(")")],1)]),t._v(" "),a("p",[t._v("Let's look at an example. Imagine we have the following Tapir endpoint:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("io"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("circe"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("generic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("generic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("json"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("circe"),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(" Book"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("title"),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(" year"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" addBook"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" PublicEndpoint"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Book"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n infallibleEndpoint\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("post\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("in"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"books"')]),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("in"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"add"')]),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("in"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n jsonBody"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Book"),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("description"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"The book to add"')]),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("example"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Book"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Pride and Prejudice"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1813")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("in"),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 builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"X-Auth-Token"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("description"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"The token is 'secret'\"")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("And a possible implementation:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("UIO\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" bookAddLogic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("book"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Book"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" token"),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(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),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("Just like you can create an http4s route by calling "),a("code",[t._v("toRoute")]),t._v(" and passing an implementation, call "),a("code",[t._v("toGraphQL")]),t._v(" to create a GraphQL API:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interop"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_ "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// summons 'toGraphQL' extension")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" addBook"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toGraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("bookAddLogic _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tupled"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("That's it! You can combine multiple "),a("code",[t._v("GraphQL")]),t._v(" objects using "),a("code",[t._v("|+|")]),t._v(" and expose the result using one of Caliban's adapters.")]),t._v(" "),a("p",[t._v("If you want to reuse "),a("code",[t._v("bookAddLogic")]),t._v(" for both GraphQL and regular HTTP, you can turn your "),a("code",[t._v("Endpoint")]),t._v(" into a "),a("code",[t._v("ServerEndpoint")]),t._v(" by calling "),a("code",[t._v(".serverLogicSuccess")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sttp"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tapir"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("server"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ServerEndpoint\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" addBookEndpoint"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ServerEndpoint"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Full"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Book"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" UIO"),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 addBook"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("serverLogicSuccess"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("book"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" token"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" bookAddLogic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("book"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" token"),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("p",[t._v("This can then be used to generate both an HTTP route (e.g. "),a("code",[t._v("toRoutes")]),t._v(" with http4s) and a GraphQL API ("),a("code",[t._v(".toGraphQL")]),t._v(").")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent:nest extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" addBookEndpoint"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toGraphQL\n")])])]),a("p",[t._v("You can find a "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/tapir",target:"_blank",rel:"noopener noreferrer"}},[t._v("full example"),a("OutboundLink")],1),t._v(" on github.")]),t._v(" "),a("h3",{attrs:{id:"graphql-restrictions"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#graphql-restrictions"}},[t._v("#")]),t._v(" GraphQL restrictions")]),t._v(" "),a("p",[a("a",{attrs:{href:"https://spec.graphql.org/June2018/#sec-Operation-Name-Uniqueness",target:"_blank",rel:"noopener noreferrer"}},[t._v("GraphQL spec"),a("OutboundLink")],1),t._v(" requires unique naming for all operations.")]),t._v(" "),a("p",[t._v("To customize the "),a("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"),a("OutboundLink")],1),t._v(" of an operation use "),a("code",[t._v("EndpointInfo.name")])]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("endpoint\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"overrideName"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/31.86d5b347.js b/docs/assets/js/31.86d5b347.js deleted file mode 100644 index e2ca5828df..0000000000 --- a/docs/assets/js/31.86d5b347.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[31],{312:function(t,e,n){"use strict";n.r(e);var r=n(14),o=Object(r.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"introspection"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#introspection"}},[t._v("#")]),t._v(" Introspection")]),t._v(" "),e("p",[t._v("Introspection queries are fully supported, which means you can use your favorite tool to inspect your schema and generate documentation for free.")]),t._v(" "),e("p",[t._v("Here's an example of documentation generated by introspection in "),e("a",{attrs:{href:"https://altair.sirmuel.design/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Altair GraphQL Client"),e("OutboundLink")],1),t._v(":")]),t._v(" "),e("p",[e("img",{attrs:{src:"/caliban/altair.png",alt:"altair screenshot"}})]),t._v(" "),e("p",[t._v("It is possible to disable introspection when executing a query by passing "),e("code",[t._v("Configurator.setEnableIntrospection(false)")]),t._v(" to the "),e("code",[t._v("configure")]),t._v(" function of your http/ws interpreter.")])])}),[],!1,null,null,null);e.default=o.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/32.73130b5d.js b/docs/assets/js/31.c29a55e2.js similarity index 99% rename from docs/assets/js/32.73130b5d.js rename to docs/assets/js/31.c29a55e2.js index 7a1ed94479..e538eb6a97 100644 --- a/docs/assets/js/32.73130b5d.js +++ b/docs/assets/js/31.c29a55e2.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[32],{313:function(t,a,s){"use strict";s.r(a);var n=s(14),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"laminext-integration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#laminext-integration"}},[t._v("#")]),t._v(" Laminext Integration")]),t._v(" "),a("p",[t._v("If you are using the Scala.js framework "),a("a",{attrs:{href:"https://laminar.dev",target:"_blank",rel:"noopener noreferrer"}},[t._v("Laminar"),a("OutboundLink")],1),t._v(", there is a module that makes the integration even nicer, with support for subscriptions.\nIt is depending on "),a("a",{attrs:{href:"https://laminext.dev",target:"_blank",rel:"noopener noreferrer"}},[t._v("Laminext"),a("OutboundLink")],1),t._v(", a library that provides nice little helpers for Laminar, in particular for using "),a("code",[t._v("Fetch")]),t._v(" and "),a("code",[t._v("WebSocket")]),t._v(".")]),t._v(" "),a("p",[t._v("To use it, import the "),a("code",[t._v("caliban-client-laminext")]),t._v(" module:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-client-laminext"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v("\n")])])]),a("p",[t._v("Add the following import to your code:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("client"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("laminext"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n")])])]),a("p",[t._v("This import adds an extension method "),a("code",[t._v("toEventStream(uri)")]),t._v(" to "),a("code",[t._v("SelectionBuilder")]),t._v(", which is similar to "),a("code",[t._v("toRequest")]),t._v(" except it creates an "),a("code",[t._v("EventStream")]),t._v(" instead of an sttp "),a("code",[t._v("Request")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" characters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Var"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Var"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Nil"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" uri "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://localhost:8088/api/graphql"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" getCharacters "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Client"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toEventStream"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("uri"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" view"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Div "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" \n div"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Characters: "')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n getCharacters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("collectRight "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("set _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n child "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("signal"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" div"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mkString"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('", "')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("To use subscriptions, you first need to create a "),a("code",[t._v("WebSocket")]),t._v(" with protocol "),a("code",[t._v("graphql-ws")]),t._v(". Use the extension method "),a("code",[t._v(".graphql")]),t._v(" instead of "),a("code",[t._v(".text")]),t._v(" or "),a("code",[t._v(".json")]),t._v(".\nThen use the extension method "),a("code",[t._v("toSubscription")]),t._v(" on your "),a("code",[t._v("SelectionBuilder")]),t._v(" and pass the "),a("code",[t._v("WebSocket")]),t._v(" object.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" ws "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" WebSocket"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("url"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ws://localhost:8088/ws/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"graphql-ws"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("graphql"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("build"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" deletedCharacters "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Subscriptions"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characterDeleted"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toSubscription"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ws"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("Finally, you can use "),a("code",[t._v("ws.connect")]),t._v(" to connect the "),a("code",[t._v("WebSocket")]),t._v(", "),a("code",[t._v("ws.init()")]),t._v(" to initialize the communication with the graphql server and "),a("code",[t._v(".received")]),t._v(" to get an "),a("code",[t._v("EventStream")]),t._v(" of the type returned by your subscription.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("ws"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("connect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\nws"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("connected\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ws"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("init"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("flatMap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" deletedCharacters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("received"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("collectRight"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("update"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("filterNot"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_ "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n")])])]),a("p",[t._v("There is a full example in the "),a("code",[t._v("test")]),t._v(" folder of the "),a("code",[t._v("caliban-client-laminext")]),t._v(" module.\nTo use it:")]),t._v(" "),a("ul",[a("li",[t._v("run "),a("code",[t._v("ExampleApp")]),t._v(" of the http4s server example (it supports CORS)")]),t._v(" "),a("li",[t._v("run "),a("code",[t._v("clientLaminextJS/Test/fastLinkJS")]),t._v(" to compile the Scala.js code")]),t._v(" "),a("li",[t._v("run "),a("code",[t._v("yarn install")]),t._v(" and "),a("code",[t._v("yarn exec vite")]),t._v(" in the "),a("code",[t._v("caliban-client-laminext")]),t._v(" folder")]),t._v(" "),a("li",[t._v("the example page will be running on "),a("a",{attrs:{href:"http://localhost:3000",target:"_blank",rel:"noopener noreferrer"}},[t._v("http://localhost:3000"),a("OutboundLink")],1)])])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[31],{312:function(t,a,s){"use strict";s.r(a);var n=s(14),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"laminext-integration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#laminext-integration"}},[t._v("#")]),t._v(" Laminext Integration")]),t._v(" "),a("p",[t._v("If you are using the Scala.js framework "),a("a",{attrs:{href:"https://laminar.dev",target:"_blank",rel:"noopener noreferrer"}},[t._v("Laminar"),a("OutboundLink")],1),t._v(", there is a module that makes the integration even nicer, with support for subscriptions.\nIt is depending on "),a("a",{attrs:{href:"https://laminext.dev",target:"_blank",rel:"noopener noreferrer"}},[t._v("Laminext"),a("OutboundLink")],1),t._v(", a library that provides nice little helpers for Laminar, in particular for using "),a("code",[t._v("Fetch")]),t._v(" and "),a("code",[t._v("WebSocket")]),t._v(".")]),t._v(" "),a("p",[t._v("To use it, import the "),a("code",[t._v("caliban-client-laminext")]),t._v(" module:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-client-laminext"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v("\n")])])]),a("p",[t._v("Add the following import to your code:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("client"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("laminext"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n")])])]),a("p",[t._v("This import adds an extension method "),a("code",[t._v("toEventStream(uri)")]),t._v(" to "),a("code",[t._v("SelectionBuilder")]),t._v(", which is similar to "),a("code",[t._v("toRequest")]),t._v(" except it creates an "),a("code",[t._v("EventStream")]),t._v(" instead of an sttp "),a("code",[t._v("Request")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" characters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Var"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Var"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Nil"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" uri "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://localhost:8088/api/graphql"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" getCharacters "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Client"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toEventStream"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("uri"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" view"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Div "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" \n div"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Characters: "')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n getCharacters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("collectRight "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("set _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n child "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("signal"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" div"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mkString"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('", "')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("To use subscriptions, you first need to create a "),a("code",[t._v("WebSocket")]),t._v(" with protocol "),a("code",[t._v("graphql-ws")]),t._v(". Use the extension method "),a("code",[t._v(".graphql")]),t._v(" instead of "),a("code",[t._v(".text")]),t._v(" or "),a("code",[t._v(".json")]),t._v(".\nThen use the extension method "),a("code",[t._v("toSubscription")]),t._v(" on your "),a("code",[t._v("SelectionBuilder")]),t._v(" and pass the "),a("code",[t._v("WebSocket")]),t._v(" object.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" ws "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" WebSocket"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("url"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ws://localhost:8088/ws/graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"graphql-ws"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("graphql"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("build"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" deletedCharacters "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Subscriptions"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("characterDeleted"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toSubscription"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ws"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("Finally, you can use "),a("code",[t._v("ws.connect")]),t._v(" to connect the "),a("code",[t._v("WebSocket")]),t._v(", "),a("code",[t._v("ws.init()")]),t._v(" to initialize the communication with the graphql server and "),a("code",[t._v(".received")]),t._v(" to get an "),a("code",[t._v("EventStream")]),t._v(" of the type returned by your subscription.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("ws"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("connect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\nws"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("connected\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ws"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("init"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("flatMap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" deletedCharacters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("received"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("collectRight"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" characters"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("update"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("filterNot"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_ "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n")])])]),a("p",[t._v("There is a full example in the "),a("code",[t._v("test")]),t._v(" folder of the "),a("code",[t._v("caliban-client-laminext")]),t._v(" module.\nTo use it:")]),t._v(" "),a("ul",[a("li",[t._v("run "),a("code",[t._v("ExampleApp")]),t._v(" of the http4s server example (it supports CORS)")]),t._v(" "),a("li",[t._v("run "),a("code",[t._v("clientLaminextJS/Test/fastLinkJS")]),t._v(" to compile the Scala.js code")]),t._v(" "),a("li",[t._v("run "),a("code",[t._v("yarn install")]),t._v(" and "),a("code",[t._v("yarn exec vite")]),t._v(" in the "),a("code",[t._v("caliban-client-laminext")]),t._v(" folder")]),t._v(" "),a("li",[t._v("the example page will be running on "),a("a",{attrs:{href:"http://localhost:3000",target:"_blank",rel:"noopener noreferrer"}},[t._v("http://localhost:3000"),a("OutboundLink")],1)])])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/33.b2f8ae12.js b/docs/assets/js/32.03eccd7b.js similarity index 60% rename from docs/assets/js/33.b2f8ae12.js rename to docs/assets/js/32.03eccd7b.js index 7a1778717d..56da1e4f18 100644 --- a/docs/assets/js/33.b2f8ae12.js +++ b/docs/assets/js/32.03eccd7b.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[33],{314:function(t,a,s){"use strict";s.r(a);var n=s(14),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"middleware"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#middleware"}},[t._v("#")]),t._v(" Middleware")]),t._v(" "),a("p",[t._v("Caliban allows you to perform additional actions at various levels of a query processing, via the concept of "),a("code",[t._v("Wrapper")]),t._v(". Using wrappers, you can:")]),t._v(" "),a("ul",[a("li",[t._v("verify that a query doesn't reach some limit (e.g. depth, complexity)")]),t._v(" "),a("li",[t._v("modify a query before it's executed")]),t._v(" "),a("li",[t._v("add timeouts to queries or fields")]),t._v(" "),a("li",[t._v("log each field execution time")]),t._v(" "),a("li",[t._v("support "),a("a",{attrs:{href:"https://github.com/apollographql/apollo-tracing",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Tracing"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://www.apollographql.com/docs/apollo-server/performance/caching",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Caching"),a("OutboundLink")],1),t._v(" or anything similar")]),t._v(" "),a("li",[t._v("etc.")])]),t._v(" "),a("h2",{attrs:{id:"wrapper-types"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#wrapper-types"}},[t._v("#")]),t._v(" Wrapper types")]),t._v(" "),a("p",[t._v("There are 6 basic types of wrappers:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("OverallWrapper")]),t._v(" to wrap the whole query processing")]),t._v(" "),a("li",[a("code",[t._v("ParsingWrapper")]),t._v(" to wrap the query parsing only")]),t._v(" "),a("li",[a("code",[t._v("ValidationWrapper")]),t._v(" to wrap the query validation only")]),t._v(" "),a("li",[a("code",[t._v("ExecutionWrapper")]),t._v(" to wrap the query execution only")]),t._v(" "),a("li",[a("code",[t._v("FieldWrapper")]),t._v(" to wrap each field execution")]),t._v(" "),a("li",[a("code",[t._v("IntrospectionWrapper")]),t._v(" to wrap the introspection query only")])]),t._v(" "),a("p",[t._v("Each one requires a function that takes a "),a("code",[t._v("ZIO")]),t._v(" or "),a("code",[t._v("ZQuery")]),t._v(" computation together with some contextual information (e.g. the query string) and should return another computation.")]),t._v(" "),a("p",[t._v("Let's see how to implement a wrapper that times out the whole query if its processing takes longer than 1 minute.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrappers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Wrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" wrapper "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" OverallWrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" wrap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n process"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLRequest "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" GraphQLResponse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLRequest "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" GraphQLResponse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLRequest"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timeout"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.")]),t._v("minute"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getOrElse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GraphQLResponse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n NullValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Query was interrupted after 1 minute:\\n')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("query")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("You can also combine wrappers using "),a("code",[t._v("|+|")]),t._v(" and create a wrapper that requires an effect to be run at each query using "),a("code",[t._v("EffectfulWrapper")]),t._v(".")]),t._v(" "),a("p",[t._v("To use your wrapper, call "),a("code",[t._v("GraphQL#withWrapper")]),t._v(" or its alias "),a("code",[t._v("@@")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("withWrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("wrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@ wrapper\n")])])]),a("h2",{attrs:{id:"pre-defined-wrappers"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#pre-defined-wrappers"}},[t._v("#")]),t._v(" Pre-defined wrappers")]),t._v(" "),a("p",[t._v("Caliban comes with a few pre-made wrappers in "),a("code",[t._v("caliban.wrappers.Wrappers")]),t._v(":")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("maxDepth")]),t._v(" returns a wrapper that fails queries whose depth is higher than a given value")]),t._v(" "),a("li",[a("code",[t._v("maxFields")]),t._v(" returns a wrapper that fails queries whose number of fields is higher than a given value")]),t._v(" "),a("li",[a("code",[t._v("maxCost")]),t._v(" returns a wrapper that fails queries when the estimated cost of execution exceeds a given value")]),t._v(" "),a("li",[a("code",[t._v("queryCost")]),t._v(" returns a wrapper which adds an extension field that includes the cost of executing the query")]),t._v(" "),a("li",[a("code",[t._v("timeout")]),t._v(" returns a wrapper that fails queries taking more than a specified time")]),t._v(" "),a("li",[a("code",[t._v("printErrors")]),t._v(" returns a wrapper that prints errors")]),t._v(" "),a("li",[a("code",[t._v("printSlowQueries")]),t._v(" returns a wrapper that prints slow queries")]),t._v(" "),a("li",[a("code",[t._v("logSlowQueries")]),t._v(" returns a wrapper that logs slow queries via ZIO's built-in logging")]),t._v(" "),a("li",[a("code",[t._v("onSlowQueries")]),t._v(" returns a wrapper that can run a given function on slow queries")]),t._v(" "),a("li",[a("code",[t._v("metrics")]),t._v(" returns a wrapper that adds field-level metrics (count & duration) to the schema")])]),t._v(" "),a("p",[t._v("In addition to those, Caliban also ships with some non-spec but standard wrappers")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("caliban.wrappers.ApolloTracing.apolloTracing")]),t._v(" returns a wrapper that adds tracing data into the "),a("code",[t._v("extensions")]),t._v(" field of each response following "),a("a",{attrs:{href:"https://github.com/apollographql/apollo-tracing",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Tracing"),a("OutboundLink")],1),t._v(" format.")]),t._v(" "),a("li",[a("code",[t._v("caliban.wrappers.Caching.extension")]),t._v(" returns a wrapper that computes the total cache policy for a query and stores it in the extensions of the response. The result can then be used by http adapters to set the appropriate cache headers in the response.")]),t._v(" "),a("li",[a("code",[t._v("caliban.wrappers.ApolloPersistedQueries.apolloPersistedQueries")]),t._v(" returns a wrapper that caches and retrieves query using a hash using the "),a("a",{attrs:{href:"https://github.com/apollographql/apollo-link-persisted-queries",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Persisted Queries"),a("OutboundLink")],1),t._v(" format.")])]),t._v(" "),a("p",[t._v("They can be used like this:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n maxDepth"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("50")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n timeout"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v(" seconds"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n printSlowQueries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("500")]),t._v(" millis"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n apolloTracing"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n Caching"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extension")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h2",{attrs:{id:"wrapping-the-interpreter"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#wrapping-the-interpreter"}},[t._v("#")]),t._v(" Wrapping the interpreter")]),t._v(" "),a("p",[t._v("All the wrappers mentioned above require that you don't modify the environment "),a("code",[t._v("R")]),t._v(" and the error type which is always a "),a("code",[t._v("CalibanError")]),t._v(". It is also possible to wrap your "),a("code",[t._v("GraphQLInterpreter")]),t._v(" by calling "),a("code",[t._v("wrapExecutionWith")]),t._v(" on it. This method takes in a function "),a("code",[t._v("f")]),t._v(" and returns a new "),a("code",[t._v("GraphQLInterpreter")]),t._v(" that will wrap the "),a("code",[t._v("execute")]),t._v(" method with this function "),a("code",[t._v("f")]),t._v(".")]),t._v(" "),a("p",[t._v("It is used internally to implement "),a("code",[t._v("mapError")]),t._v(" (customize errors) and "),a("code",[t._v("provide")]),t._v(" (eliminate the environment), but you can use it for other purposes such as adding a general timeout, logging response times, etc.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// change error type to String")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i2"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mapError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toString"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// provide the environment")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i3"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("provide"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("myEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// add a timeout on every query execution")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i4"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrapExecutionWith"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timeout"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("30")]),t._v(" seconds"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getOrElse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GraphQLResponse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("NullValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Timeout!"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h2",{attrs:{id:"customizing-error-responses"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#customizing-error-responses"}},[t._v("#")]),t._v(" Customizing error responses")]),t._v(" "),a("p",[t._v("During various phases of executing a query, an error may occur. Caliban renders the different instances of "),a("code",[t._v("CalibanError")]),t._v(" to a GraphQL spec compliant response. As a user, you will most likely encounter "),a("code",[t._v("ExecutionError")]),t._v(" at some point because this will encapsulate the errors in the error channel of your effects. For Caliban to be able to render some basic message about the error that occured during query execution, it is important that your error extends "),a("code",[t._v("Throwable")]),t._v(".")]),t._v(" "),a("p",[t._v("For more meaningful error handling, GraphQL spec allows for an "),a("a",{attrs:{href:"http://spec.graphql.org/June2018/#example-fce18",target:"_blank",rel:"noopener noreferrer"}},[a("code",[t._v("extension")]),a("OutboundLink")],1),t._v(" object in the error response. This object may include, for instance, "),a("code",[t._v("code")]),t._v(" information to model enum-like error codes that can be handled by a front-end. In order to generate this information, one can use the "),a("code",[t._v("mapError")]),t._v(" function on a "),a("code",[t._v("GraphQLInterpreter")]),t._v(". An example is provided below in which we map a custom domain error within an "),a("code",[t._v("ExecutionError")]),t._v(" to a meaningful error code.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ResponseValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ObjectValue\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" ExampleAppEncodableError "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Throwable "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" errorCode"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" UnauthorizedError "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" ExampleAppEncodableError "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" errorCode"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"UNAUTHORIZED"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" withErrorCodeExtensions"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n interpreter"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" interpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mapError "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err @ ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("exampleError"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ExampleAppEncodableError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("extensions "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"errorCode"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("exampleError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("errorCode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ExecutionError "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("extensions "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"errorCode"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"EXECUTION_ERROR"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ValidationError "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("extensions "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"errorCode"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"VALIDATION_ERROR"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ParsingError "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("extensions "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"errorCode"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"PARSING_ERROR"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"wrapping-the-graphql"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#wrapping-the-graphql"}},[t._v("#")]),t._v(" Wrapping the GraphQL")]),t._v(" "),a("p",[t._v("If you need to implement new functionality that involves not just changes to execution but also to the underlying\nschema you can use the higher-level "),a("code",[t._v("GraphQLAspect")]),t._v(" which allows full control of the resulting "),a("code",[t._v("GraphQL")]),t._v(" that it wraps.")]),t._v(" "),a("p",[t._v("Here is such an example that is part of the "),a("code",[t._v("federation")]),t._v(" package which makes a schema available to be used as a sub-graph in\na federated graph:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" federate"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("original"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n _service"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" _Service"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n _fieldSet"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FieldSet "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" FieldSet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_service "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _Service"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("original"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("render"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" federationDirectives"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" original\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" federated"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLAspect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" GraphQLAspect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" apply"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("original"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n federate"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("original"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"cost-estimation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#cost-estimation"}},[t._v("#")]),t._v(" Cost Estimation")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("queryCost")]),t._v(" and "),a("code",[t._v("maxCost")]),t._v(" wrappers as well as their variants can be used to estimate the cost of a query, however they require a bit\nmore set up to work properly.")]),t._v(" "),a("p",[t._v("These wrappers are in the "),a("code",[t._v("CostEstimation")]),t._v(" object which also comes with a special directive that can be used out of the box to instrument your\nschema for cost analysis.")]),t._v(" "),a("p",[t._v("Given a schema in which different fields have different costs to execute, either because they require additional network or computing resources, or database access, or they\nhave some other dependency that makes them expensive to compute. You can add the "),a("code",[t._v("CostDirective")]),t._v(" to your resolver like so:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrappers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("CostEstimation\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrappers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("CostEstimation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" SpokenLineArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("offset"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" limit"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLCost")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Compute a realtime list of all the spoken lines for this character")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLCost")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" multipliers "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"limit"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n spokenLines"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SpokenLineArgs "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLCost")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" characters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" allCharacterNames"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" getLines"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" offset"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" limit"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n characters "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" allCharacterNames"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("flatMap "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" \n names "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("foreach"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("names"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" name "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" character "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n spokenLines "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" args "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" getLines"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("offset"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("limit"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" \n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" apiWithCost "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" api @@ \n queryCost @@ "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or queryCost(f: Field => Double) to specify your own field cost estimation")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or queryCostWith(f: Field => Double)(p: Double => URIO[R, Any]) to also specify a side effect after computing the total cost")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or queryCostZIO(f: Field => URIO[R, Double]) if your field calculation returns an effect")]),t._v("\n maxCost"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CostEstimation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("costDirective"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or maxCostOrError(maxCost)(f: Double => ValidationError) to specify a different error")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or maxCostZIO(maxCost)(f: Field => URIO[R, Double]) if your field calculation returns an effect")]),t._v("\n\n")])])]),a("p",[t._v('In the above example we have provided a couple different examples. For instance, we can add the directive to both types and\nto fields. In this case the field resolver will override the type cost, however if there is no field cost then the type cost will be used.\nWe may also specify a "multipliers" argument when using arguments. This will match the argument names and use numeric argument values to multiply the base value.\nIn the above case this means that a query that specifies a '),a("code",[t._v("limit")]),t._v(" of "),a("code",[t._v("10")]),t._v(" for the "),a("code",[t._v("spokenLines")]),t._v(" field will have the base field cost multipled by 10 resulting in a total cost\nof execution of "),a("code",[t._v("1000")])]),t._v(" "),a("h2",{attrs:{id:"opentelemetry-tracing"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#opentelemetry-tracing"}},[t._v("#")]),t._v(" OpenTelemetry Tracing")]),t._v(" "),a("p",[t._v("Caliban ships with support for OpenTelemetry tracing via integration with "),a("a",{attrs:{href:"https://github.com/zio/zio-telemetry",target:"_blank",rel:"noopener noreferrer"}},[t._v("zio-telemetry"),a("OutboundLink")],1),t._v(" in the "),a("code",[t._v("caliban-tracing")]),t._v(" package.")]),t._v(" "),a("p",[t._v("In order to use tracing, first add "),a("code",[t._v("caliban-tracing")]),t._v(" to your "),a("code",[t._v("built.sbt")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-tracing"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v("\n")])])]),a("p",[t._v("Then add it to your schema as any other wrapper:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tracing"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("TracingWrapper\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("telemetry"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("opentelemetry"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Tracing\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" tracedApi "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" api @@ TracingWrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("traced\n")])])]),a("p",[t._v("This will now make sure that any effect (ZIO or ZQuery) is measured as its own span, which makes it easy to spot potential optimizations (such as sequential loading) in your schema.")]),t._v(" "),a("p",[t._v("More or less like this:")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("query |----------------------------------------------|\nfield a |-------|\nfield b |-------|\nnested field |-----------------------|\nnested field a |-------------------|\nnested field b |-------------------|\n")])])]),a("p",[t._v("which makes it easy to spot that e.g field a and field b could be resolved in parallel.")])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[32],{313:function(t,a,s){"use strict";s.r(a);var n=s(14),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"middleware"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#middleware"}},[t._v("#")]),t._v(" Middleware")]),t._v(" "),a("p",[t._v("Caliban allows you to perform additional actions at various levels of a query processing, via the concept of "),a("code",[t._v("Wrapper")]),t._v(". Using wrappers, you can:")]),t._v(" "),a("ul",[a("li",[t._v("verify that a query doesn't reach some limit (e.g. depth, complexity)")]),t._v(" "),a("li",[t._v("modify a query before it's executed")]),t._v(" "),a("li",[t._v("add timeouts to queries or fields")]),t._v(" "),a("li",[t._v("log each field execution time")]),t._v(" "),a("li",[t._v("support "),a("a",{attrs:{href:"https://github.com/apollographql/apollo-tracing",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Tracing"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://www.apollographql.com/docs/apollo-server/performance/caching",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Caching"),a("OutboundLink")],1),t._v(" or anything similar")]),t._v(" "),a("li",[t._v("etc.")])]),t._v(" "),a("h2",{attrs:{id:"wrapper-types"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#wrapper-types"}},[t._v("#")]),t._v(" Wrapper types")]),t._v(" "),a("p",[t._v("There are 6 basic types of wrappers:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("OverallWrapper")]),t._v(" to wrap the whole query processing")]),t._v(" "),a("li",[a("code",[t._v("ParsingWrapper")]),t._v(" to wrap the query parsing only")]),t._v(" "),a("li",[a("code",[t._v("ValidationWrapper")]),t._v(" to wrap the query validation only")]),t._v(" "),a("li",[a("code",[t._v("ExecutionWrapper")]),t._v(" to wrap the query execution only")]),t._v(" "),a("li",[a("code",[t._v("FieldWrapper")]),t._v(" to wrap each field execution")]),t._v(" "),a("li",[a("code",[t._v("IntrospectionWrapper")]),t._v(" to wrap the introspection query only")])]),t._v(" "),a("p",[t._v("Each one requires a function that takes a "),a("code",[t._v("ZIO")]),t._v(" or "),a("code",[t._v("ZQuery")]),t._v(" computation together with some contextual information (e.g. the query string) and should return another computation.")]),t._v(" "),a("p",[t._v("Let's see how to implement a wrapper that times out the whole query if its processing takes longer than 1 minute.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrappers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Wrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" wrapper "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" OverallWrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" wrap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n process"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLRequest "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" GraphQLResponse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLRequest "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" GraphQLResponse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLRequest"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n process"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timeout"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.")]),t._v("minute"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getOrElse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GraphQLResponse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n NullValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Query was interrupted after 1 minute:\\n')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("query")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("You can also combine wrappers using "),a("code",[t._v("|+|")]),t._v(" and create a wrapper that requires an effect to be run at each query using "),a("code",[t._v("EffectfulWrapper")]),t._v(".")]),t._v(" "),a("p",[t._v("To use your wrapper, call "),a("code",[t._v("GraphQL#withWrapper")]),t._v(" or its alias "),a("code",[t._v("@@")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("withWrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("wrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@ wrapper\n")])])]),a("h2",{attrs:{id:"pre-defined-wrappers"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#pre-defined-wrappers"}},[t._v("#")]),t._v(" Pre-defined wrappers")]),t._v(" "),a("p",[t._v("Caliban comes with a few pre-made wrappers in "),a("code",[t._v("caliban.wrappers.Wrappers")]),t._v(":")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("maxDepth")]),t._v(" returns a wrapper that fails queries whose depth is higher than a given value")]),t._v(" "),a("li",[a("code",[t._v("maxFields")]),t._v(" returns a wrapper that fails queries whose number of fields is higher than a given value")]),t._v(" "),a("li",[a("code",[t._v("maxCost")]),t._v(" returns a wrapper that fails queries when the estimated cost of execution exceeds a given value")]),t._v(" "),a("li",[a("code",[t._v("queryCost")]),t._v(" returns a wrapper which adds an extension field that includes the cost of executing the query")]),t._v(" "),a("li",[a("code",[t._v("timeout")]),t._v(" returns a wrapper that fails queries taking more than a specified time")]),t._v(" "),a("li",[a("code",[t._v("printErrors")]),t._v(" returns a wrapper that prints errors")]),t._v(" "),a("li",[a("code",[t._v("printSlowQueries")]),t._v(" returns a wrapper that prints slow queries")]),t._v(" "),a("li",[a("code",[t._v("logSlowQueries")]),t._v(" returns a wrapper that logs slow queries via ZIO's built-in logging")]),t._v(" "),a("li",[a("code",[t._v("onSlowQueries")]),t._v(" returns a wrapper that can run a given function on slow queries")]),t._v(" "),a("li",[a("code",[t._v("metrics")]),t._v(" returns a wrapper that adds field-level metrics (count & duration) to the schema")])]),t._v(" "),a("p",[t._v("In addition to those, Caliban also ships with some non-spec but standard wrappers")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("caliban.wrappers.ApolloTracing.apolloTracing")]),t._v(" returns a wrapper that adds tracing data into the "),a("code",[t._v("extensions")]),t._v(" field of each response following "),a("a",{attrs:{href:"https://github.com/apollographql/apollo-tracing",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Tracing"),a("OutboundLink")],1),t._v(" format.")]),t._v(" "),a("li",[a("code",[t._v("caliban.wrappers.Caching.extension")]),t._v(" returns a wrapper that computes the total cache policy for a query and stores it in the extensions of the response. The result can then be used by http adapters to set the appropriate cache headers in the response.")]),t._v(" "),a("li",[a("code",[t._v("caliban.wrappers.ApolloPersistedQueries.apolloPersistedQueries")]),t._v(" returns a wrapper that caches and retrieves query using a hash using the "),a("a",{attrs:{href:"https://github.com/apollographql/apollo-link-persisted-queries",target:"_blank",rel:"noopener noreferrer"}},[t._v("Apollo Persisted Queries"),a("OutboundLink")],1),t._v(" format.")])]),t._v(" "),a("p",[t._v("They can be used like this:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n maxDepth"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("50")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n timeout"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v(" seconds"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n printSlowQueries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("500")]),t._v(" millis"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n apolloTracing"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" @@\n Caching"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extension")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h2",{attrs:{id:"wrapping-the-interpreter"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#wrapping-the-interpreter"}},[t._v("#")]),t._v(" Wrapping the interpreter")]),t._v(" "),a("p",[t._v("All the wrappers mentioned above require that you don't modify the environment "),a("code",[t._v("R")]),t._v(" and the error type which is always a "),a("code",[t._v("CalibanError")]),t._v(". It is also possible to wrap your "),a("code",[t._v("GraphQLInterpreter")]),t._v(" by calling "),a("code",[t._v("wrapExecutionWith")]),t._v(" on it. This method takes in a function "),a("code",[t._v("f")]),t._v(" and returns a new "),a("code",[t._v("GraphQLInterpreter")]),t._v(" that will wrap the "),a("code",[t._v("execute")]),t._v(" method with this function "),a("code",[t._v("f")]),t._v(".")]),t._v(" "),a("p",[t._v("It is used internally to implement "),a("code",[t._v("mapError")]),t._v(" (customize errors) and "),a("code",[t._v("provide")]),t._v(" (eliminate the environment), but you can use it for other purposes such as adding a general timeout, logging response times, etc.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// change error type to String")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i2"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mapError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toString"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// provide the environment")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i3"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("provide"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("myEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// add a timeout on every query execution")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" i4"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrapExecutionWith"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timeout"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("30")]),t._v(" seconds"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getOrElse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GraphQLResponse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("NullValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Timeout!"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h2",{attrs:{id:"customizing-error-responses"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#customizing-error-responses"}},[t._v("#")]),t._v(" Customizing error responses")]),t._v(" "),a("p",[t._v("During various phases of executing a query, an error may occur. Caliban renders the different instances of "),a("code",[t._v("CalibanError")]),t._v(" to a GraphQL spec compliant response. As a user, you will most likely encounter "),a("code",[t._v("ExecutionError")]),t._v(" at some point because this will encapsulate the errors in the error channel of your effects. For Caliban to be able to render some basic message about the error that occured during query execution, it is important that your error extends "),a("code",[t._v("Throwable")]),t._v(".")]),t._v(" "),a("p",[t._v("For more meaningful error handling, GraphQL spec allows for an "),a("a",{attrs:{href:"http://spec.graphql.org/June2018/#example-fce18",target:"_blank",rel:"noopener noreferrer"}},[a("code",[t._v("extension")]),a("OutboundLink")],1),t._v(" object in the error response. This object may include, for instance, "),a("code",[t._v("code")]),t._v(" information to model enum-like error codes that can be handled by a front-end. In order to generate this information, one can use the "),a("code",[t._v("mapError")]),t._v(" function on a "),a("code",[t._v("GraphQLInterpreter")]),t._v(". An example is provided below in which we map a custom domain error within an "),a("code",[t._v("ExecutionError")]),t._v(" to a meaningful error code.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ResponseValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ObjectValue\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" ExampleAppEncodableError "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Throwable "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" errorCode"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" UnauthorizedError "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" ExampleAppEncodableError "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" errorCode"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"UNAUTHORIZED"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" withErrorCodeExtensions"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n interpreter"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLInterpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" interpreter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mapError "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err @ ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("exampleError"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ExampleAppEncodableError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("extensions "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"errorCode"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("exampleError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("errorCode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ExecutionError "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("extensions "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"errorCode"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"EXECUTION_ERROR"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ValidationError "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("extensions "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"errorCode"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"VALIDATION_ERROR"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ParsingError "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("extensions "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ObjectValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"errorCode"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"PARSING_ERROR"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"wrapping-the-graphql"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#wrapping-the-graphql"}},[t._v("#")]),t._v(" Wrapping the GraphQL")]),t._v(" "),a("p",[t._v("If you need to implement new functionality that involves not just changes to execution but also to the underlying\nschema you can use the higher-level "),a("code",[t._v("GraphQLAspect")]),t._v(" which allows full control of the resulting "),a("code",[t._v("GraphQL")]),t._v(" that it wraps.")]),t._v(" "),a("p",[t._v("Here is such an example that is part of the "),a("code",[t._v("federation")]),t._v(" package which makes a schema available to be used as a sub-graph in\na federated graph:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" federate"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("original"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n _service"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" _Service"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n _fieldSet"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FieldSet "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" FieldSet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_service "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _Service"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("original"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("render"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" federationDirectives"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" original\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" federated"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQLAspect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" GraphQLAspect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Nothing")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" apply"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("original"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("R1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n federate"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("original"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"cost-estimation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#cost-estimation"}},[t._v("#")]),t._v(" Cost Estimation")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("queryCost")]),t._v(" and "),a("code",[t._v("maxCost")]),t._v(" wrappers as well as their variants can be used to estimate the cost of a query, however they require a bit\nmore set up to work properly.")]),t._v(" "),a("p",[t._v("These wrappers are in the "),a("code",[t._v("CostEstimation")]),t._v(" object which also comes with a special directive that can be used out of the box to instrument your\nschema for cost analysis.")]),t._v(" "),a("p",[t._v("Given a schema in which different fields have different costs to execute, either because they require additional network or computing resources, or database access, or they\nhave some other dependency that makes them expensive to compute. You can add the "),a("code",[t._v("CostDirective")]),t._v(" to your resolver like so:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrappers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("CostEstimation\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wrappers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("CostEstimation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" SpokenLineArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("offset"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" limit"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLCost")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Compute a realtime list of all the spoken lines for this character")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLCost")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" multipliers "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"limit"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n spokenLines"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SpokenLineArgs "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLCost")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" characters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" allCharacterNames"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" getLines"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" offset"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" limit"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n characters "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" allCharacterNames"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("flatMap "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" \n names "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("foreach"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("names"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" name "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" character "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n spokenLines "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" args "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" getLines"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("offset"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("limit"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" \n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" apiWithCost "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" api @@ \n queryCost @@ "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or queryCost(f: Field => Double) to specify your own field cost estimation")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or queryCostWith(f: Field => Double)(p: Double => URIO[R, Any]) to also specify a side effect after computing the total cost")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or queryCostZIO(f: Field => URIO[R, Double]) if your field calculation returns an effect")]),t._v("\n maxCost"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CostEstimation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("costDirective"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or maxCostOrError(maxCost)(f: Double => ValidationError) to specify a different error")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or maxCostZIO(maxCost)(f: Field => URIO[R, Double]) if your field calculation returns an effect")]),t._v("\n\n")])])]),a("p",[t._v('In the above example we have provided a couple different examples. For instance, we can add the directive to both types and\nto fields. In this case the field resolver will override the type cost, however if there is no field cost then the type cost will be used.\nWe may also specify a "multipliers" argument when using arguments. This will match the argument names and use numeric argument values to multiply the base value.\nIn the above case this means that a query that specifies a '),a("code",[t._v("limit")]),t._v(" of "),a("code",[t._v("10")]),t._v(" for the "),a("code",[t._v("spokenLines")]),t._v(" field will have the base field cost multipled by 10 resulting in a total cost\nof execution of "),a("code",[t._v("1000")])]),t._v(" "),a("h2",{attrs:{id:"opentelemetry-tracing"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#opentelemetry-tracing"}},[t._v("#")]),t._v(" OpenTelemetry Tracing")]),t._v(" "),a("p",[t._v("Caliban ships with support for OpenTelemetry tracing via integration with "),a("a",{attrs:{href:"https://github.com/zio/zio-telemetry",target:"_blank",rel:"noopener noreferrer"}},[t._v("zio-telemetry"),a("OutboundLink")],1),t._v(" in the "),a("code",[t._v("caliban-tracing")]),t._v(" package.")]),t._v(" "),a("p",[t._v("In order to use tracing, first add "),a("code",[t._v("caliban-tracing")]),t._v(" to your "),a("code",[t._v("built.sbt")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-tracing"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v("\n")])])]),a("p",[t._v("Then add it to your schema as any other wrapper:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tracing"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("TracingWrapper\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("telemetry"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("opentelemetry"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Tracing\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" tracedApi "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" api @@ TracingWrapper"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("traced\n")])])]),a("p",[t._v("This will now make sure that any effect (ZIO or ZQuery) is measured as its own span, which makes it easy to spot potential optimizations (such as sequential loading) in your schema.")]),t._v(" "),a("p",[t._v("More or less like this:")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("query |----------------------------------------------|\nfield a |-------|\nfield b |-------|\nnested field |-----------------------|\nnested field a |-------------------|\nnested field b |-------------------|\n")])])]),a("p",[t._v("which makes it easy to spot that e.g field a and field b could be resolved in parallel.")])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/34.8425abc5.js b/docs/assets/js/33.bc31e9d4.js similarity index 99% rename from docs/assets/js/34.8425abc5.js rename to docs/assets/js/33.bc31e9d4.js index 0147ee6979..97981ef84f 100644 --- a/docs/assets/js/34.8425abc5.js +++ b/docs/assets/js/33.bc31e9d4.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[34],{315:function(t,s,a){"use strict";a.r(s);var e=a(14),n=Object(e.a)({},(function(){var t=this,s=t._self._c;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("an 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(".")]),t._v("Batched"),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(" Chunk"),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 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("Exit")]),t._v(" ("),s("code",[t._v("fail")]),t._v(" for an error and "),s("code",[t._v("succeed")]),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(" Chunk"),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("exit"),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("Exit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fail"),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("Exit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),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(" "),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("\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.fromZIO")])]),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/series/2.x/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/series/2.x/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/series/2.x/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",[s("code",[t._v("ZQuery")]),t._v(" has a lot of operators that are similar to "),s("code",[t._v("ZIO")]),t._v(", such as "),s("code",[t._v(".optional")]),t._v(", etc.\nNote that just like "),s("code",[t._v("ZIO")]),t._v(", a field returning a "),s("code",[t._v("ZQuery")]),t._v(" will be executed only when it is requested by the client.")])]),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")])])]),s("h2",{attrs:{id:"defer-support-experimental"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#defer-support-experimental"}},[t._v("#")]),t._v(" @defer support (experimental)")]),t._v(" "),s("p",[t._v("Caliban provides experimental support for the "),s("code",[t._v("@defer")]),t._v(" directive.\nThis directive allows you to delay the execution of a fragment until after the main query has been resolved.\nThis allows the client to load faster by prioritizing the loading of the more important data first.")]),t._v(" "),s("p",[t._v("The client is able to submit a query that looks like this:")]),t._v(" "),s("div",{staticClass:"language-graphql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-graphql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("query")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("characters")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("name")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("nicknames")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@defer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("label")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"characterDetails"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("role")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("origin")]),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("The server can now split the query returning the non-deferred components first")]),t._v(" "),s("div",{staticClass:"language-json extra-class"},[s("pre",{pre:!0,attrs:{class:"language-json"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"data"')]),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 property"}},[t._v('"characters"')]),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 punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"name"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"James Holden"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"nicknames"')]),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 string"}},[t._v('"Hoss"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Holden"')]),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 "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"name"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Naomi Nagata"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"nicknames"')]),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 string"}},[t._v('"Naomi"')]),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("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"hasNext"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("The deferred fragment will be delivered in a separate response")]),t._v(" "),s("div",{staticClass:"language-json extra-class"},[s("pre",{pre:!0,attrs:{class:"language-json"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"incremental"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[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 property"}},[t._v('"label"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"characterDetails"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"path"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"characters"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),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 property"}},[t._v('"data"')]),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 property"}},[t._v('"role"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Captain"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"origin"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Earth"')]),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(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"label"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"characterDetails"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"path"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"characters"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),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 property"}},[t._v('"data"')]),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 property"}},[t._v('"role"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Executive Officer"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"origin"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Belter"')]),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("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"hasNext"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("The final response may simply be an empty body with "),s("code",[t._v("hasNext: false")]),t._v(" as the only key.")]),t._v(" "),s("div",{staticClass:"language-json extra-class"},[s("pre",{pre:!0,attrs:{class:"language-json"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"hasNext"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h3",{attrs:{id:"usage"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#usage"}},[t._v("#")]),t._v(" Usage")]),t._v(" "),s("p",[t._v("By default, Caliban will not allow clients to send requests containing the "),s("code",[t._v("@defer")]),t._v(" directive. This is because it can substantially\nincrease the runtime cost of a query. To enable this feature you must explicitly opt-in to it.\nYou do this by adding the "),s("code",[t._v("@@ DeferSupport.defer")]),t._v(" aspect to your graph definition. This will inform the executor\nthat it may process queries that contain defer and will add the "),s("code",[t._v("@defer")]),t._v(" directive as a supported directive in the schema.")]),t._v(" "),s("p",[t._v("Additionally, you must make sure that your client is able to handle deferred responses. This requires special support from the client\nbecause the response will be streamed to the client in multiple parts instead of as a single json body.")]),t._v(" "),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),s("p",[t._v("This optimization is completely optional from the server-side, the client shouldn't rely on any particular query splitting strategy as the server\nwill try to optimize the query to reduce performance penalties. For instance, if you defer a pure field (i.e. a field that doesn't require any effect) the server\nmay decide it is cheaper to simply return that as part of the main response instead of splitting it.")])]),t._v(" "),s("p",[t._v("Note: We highly recommend that you use one of the provided adapters when using this feature. These come with built-in support\nfor defer and will automatically unwrap the result of the query correctly. If you are writing your own adapter you will need to\nmanually handle the streaming result returned from the executor.")])])}),[],!1,null,null,null);s.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[33],{314:function(t,s,a){"use strict";a.r(s);var e=a(14),n=Object(e.a)({},(function(){var t=this,s=t._self._c;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("an 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(".")]),t._v("Batched"),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(" Chunk"),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 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("Exit")]),t._v(" ("),s("code",[t._v("fail")]),t._v(" for an error and "),s("code",[t._v("succeed")]),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(" Chunk"),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("exit"),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("Exit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fail"),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("Exit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),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(" "),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("\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.fromZIO")])]),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/series/2.x/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/series/2.x/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/series/2.x/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",[s("code",[t._v("ZQuery")]),t._v(" has a lot of operators that are similar to "),s("code",[t._v("ZIO")]),t._v(", such as "),s("code",[t._v(".optional")]),t._v(", etc.\nNote that just like "),s("code",[t._v("ZIO")]),t._v(", a field returning a "),s("code",[t._v("ZQuery")]),t._v(" will be executed only when it is requested by the client.")])]),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")])])]),s("h2",{attrs:{id:"defer-support-experimental"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#defer-support-experimental"}},[t._v("#")]),t._v(" @defer support (experimental)")]),t._v(" "),s("p",[t._v("Caliban provides experimental support for the "),s("code",[t._v("@defer")]),t._v(" directive.\nThis directive allows you to delay the execution of a fragment until after the main query has been resolved.\nThis allows the client to load faster by prioritizing the loading of the more important data first.")]),t._v(" "),s("p",[t._v("The client is able to submit a query that looks like this:")]),t._v(" "),s("div",{staticClass:"language-graphql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-graphql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("query")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("characters")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("name")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("nicknames")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@defer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("label")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"characterDetails"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("role")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("origin")]),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("The server can now split the query returning the non-deferred components first")]),t._v(" "),s("div",{staticClass:"language-json extra-class"},[s("pre",{pre:!0,attrs:{class:"language-json"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"data"')]),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 property"}},[t._v('"characters"')]),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 punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"name"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"James Holden"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"nicknames"')]),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 string"}},[t._v('"Hoss"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Holden"')]),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 "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"name"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Naomi Nagata"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"nicknames"')]),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 string"}},[t._v('"Naomi"')]),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("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"hasNext"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("The deferred fragment will be delivered in a separate response")]),t._v(" "),s("div",{staticClass:"language-json extra-class"},[s("pre",{pre:!0,attrs:{class:"language-json"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"incremental"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[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 property"}},[t._v('"label"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"characterDetails"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"path"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"characters"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),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 property"}},[t._v('"data"')]),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 property"}},[t._v('"role"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Captain"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"origin"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Earth"')]),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(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"label"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"characterDetails"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"path"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"characters"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),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 property"}},[t._v('"data"')]),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 property"}},[t._v('"role"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Executive Officer"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"origin"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Belter"')]),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("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"hasNext"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("The final response may simply be an empty body with "),s("code",[t._v("hasNext: false")]),t._v(" as the only key.")]),t._v(" "),s("div",{staticClass:"language-json extra-class"},[s("pre",{pre:!0,attrs:{class:"language-json"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v('"hasNext"')]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h3",{attrs:{id:"usage"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#usage"}},[t._v("#")]),t._v(" Usage")]),t._v(" "),s("p",[t._v("By default, Caliban will not allow clients to send requests containing the "),s("code",[t._v("@defer")]),t._v(" directive. This is because it can substantially\nincrease the runtime cost of a query. To enable this feature you must explicitly opt-in to it.\nYou do this by adding the "),s("code",[t._v("@@ DeferSupport.defer")]),t._v(" aspect to your graph definition. This will inform the executor\nthat it may process queries that contain defer and will add the "),s("code",[t._v("@defer")]),t._v(" directive as a supported directive in the schema.")]),t._v(" "),s("p",[t._v("Additionally, you must make sure that your client is able to handle deferred responses. This requires special support from the client\nbecause the response will be streamed to the client in multiple parts instead of as a single json body.")]),t._v(" "),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),s("p",[t._v("This optimization is completely optional from the server-side, the client shouldn't rely on any particular query splitting strategy as the server\nwill try to optimize the query to reduce performance penalties. For instance, if you defer a pure field (i.e. a field that doesn't require any effect) the server\nmay decide it is cheaper to simply return that as part of the main response instead of splitting it.")])]),t._v(" "),s("p",[t._v("Note: We highly recommend that you use one of the provided adapters when using this feature. These come with built-in support\nfor defer and will automatically unwrap the result of the query correctly. If you are writing your own adapter you will need to\nmanually handle the streaming result returned from the executor.")])])}),[],!1,null,null,null);s.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/35.0a127519.js b/docs/assets/js/34.06413a27.js similarity index 99% rename from docs/assets/js/35.0a127519.js rename to docs/assets/js/34.06413a27.js index 55d0e6a13c..b2ff6b97c7 100644 --- a/docs/assets/js/35.0a127519.js +++ b/docs/assets/js/34.06413a27.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[35],{316:function(t,s,a){"use strict";a.r(s);var n=a(14),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"relay-connections"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#relay-connections"}},[t._v("#")]),t._v(" Relay Connections")]),t._v(" "),s("p",[t._v("The "),s("em",[t._v("GraphQL Cursors Connection Specification")]),t._v(" is an additional spec that extends GraphQL to support paginating over collections in a standardized way, defined by facebook's "),s("a",{attrs:{href:"https://relay.dev/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Relay GraphQL client"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("p",[t._v("The spec defines several types:")]),t._v(" "),s("ul",[s("li",[t._v("Connections - the paginated 1:N relationship itself")]),t._v(" "),s("li",[t._v("PageInfo - an object describing the pagination information of the current relation")]),t._v(" "),s("li",[t._v("Edge - a type describing each item in the pagination")]),t._v(" "),s("li",[t._v("Node - the type that's being paginated over")])]),t._v(" "),s("p",[t._v("An example query for a connection field looks something like this:")]),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 punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property-query"}},[t._v("queryName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("first")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("after")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"cursor"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("pageInfo")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("hasNextPage")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("hasPreviousPage")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("startCursor")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("endCursor")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("edges")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("cursor")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("node")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("id")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# additional fields")]),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("The field can be paginated forwards by using "),s("code",[t._v("first")]),t._v(" (number of items) and "),s("code",[t._v("after")]),t._v(" (the current cursor), or backwards by using "),s("code",[t._v("last")]),t._v(" (number of items) and "),s("code",[t._v("before")]),t._v(" (the cursor).")]),t._v(" "),s("p",[t._v("Caliban ships with a set of abstract classes to make it easier to use Relay connections in your schema:")]),t._v(" "),s("div",{staticClass:"language-scala mdoc:silent extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("relay"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The entity you want to paginate over")]),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(" Item"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The specific edge type for your connection.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The default cursor implementation is a base64 encoded index offset,")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// but you can easily implement your own cursor to support e.g")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// cursor based pagination from your database.")]),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(" ItemEdge"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("cursor"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Base64Cursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" node"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Item"),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(" Edge"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Base64Cursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Item"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" ItemEdge "),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(" apply"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Item"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" i"),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(" ItemEdge "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ItemEdge"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Base64Cursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" x"),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 comment"}},[t._v("// The top level connection itself")]),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(" ItemConnection"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n pageInfo"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" PageInfo"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n edges"),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("ItemEdge"),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("extends")]),t._v(" Connection"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ItemEdge"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" ItemConnection "),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(" fromList "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Connection"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromList"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ItemConnection"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("apply"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ItemEdge"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("apply"),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 punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The arguments for your resolver.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// These are the minimal set of fields needed,")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// but you can easily customize it to add e.g")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// sorting or filtering.")]),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(" Args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n first"),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 last"),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 before"),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("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n after"),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("String")]),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("extends")]),t._v(" PaginationArgs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Base64Cursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\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(" Query"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("connection"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Args "),s("span",{pre:!0,attrs:{class:"token keyword"}},[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(" CalibanError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ItemConnection"),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("\n RootResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Query"),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("\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 pageInfo "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" Pagination"),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("\n items "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ItemConnection"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromList"),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("Item"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Item"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Item"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"3"')]),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(" pageInfo"),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(" items\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("h2",{attrs:{id:"cursors"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#cursors"}},[t._v("#")]),t._v(" Cursors")]),t._v(" "),s("p",[t._v("It's possible to implement your own cursor type to match with the underlying data source you have. This may be a database cursor, a date offset or something else which you use to efficiently filter your result set.")]),t._v(" "),s("p",[t._v("Start off by implementing a case class to represent your cursor:")]),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(" ElasticCursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),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("p",[t._v("To turn your case class into a usable cursor, you need to do two things: implement the "),s("code",[t._v("Cursor")]),t._v(" trait and specify a "),s("code",[t._v("Schema")]),t._v(" for the case class to make sure it's always serialized as a scalar value.")]),t._v(" "),s("p",[t._v("First, let's implement the trait:")]),t._v(" "),s("div",{staticClass:"language-scala mdoc:silent extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("java"),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("Base64\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[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("Try\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(" ElasticCursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),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("object")]),t._v(" ElasticCursor "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),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(" decoder "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Base64"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getDecoder"),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("lazy")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" encoder "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Base64"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getEncoder"),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("implicit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" cursor"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Cursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ElasticCursor"),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 keyword"}},[t._v("new")]),t._v(" Cursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ElasticCursor"),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("type")]),t._v(" T "),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 keyword"}},[t._v("def")]),t._v(" encode"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ElasticCursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),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 punctuation"}},[t._v("{")]),t._v("\n encoder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("encodeToString"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string-interpolation"}},[s("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"cursor:')]),s("span",{pre:!0,attrs:{class:"token interpolation"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),s("span",{pre:!0,attrs:{class:"token expression"}},[t._v("a"),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 string"}},[t._v('"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getBytes"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"UTF-8"')]),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 keyword"}},[t._v("def")]),t._v(" decode"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),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(" Either"),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(" ElasticCursor"),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 Try"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n ElasticCursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),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("decoder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("decode"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),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 string"}},[t._v('"UTF-8"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("replaceFirst"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"cursor:"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toEither"),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("map"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toString"),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("def")]),t._v(" value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ElasticCursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" T "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" c"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value\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("and the schema:")]),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(" schema"),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(" ElasticCursor"),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("\n Cursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ElasticCursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("encode\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[34],{315:function(t,s,a){"use strict";a.r(s);var n=a(14),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"relay-connections"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#relay-connections"}},[t._v("#")]),t._v(" Relay Connections")]),t._v(" "),s("p",[t._v("The "),s("em",[t._v("GraphQL Cursors Connection Specification")]),t._v(" is an additional spec that extends GraphQL to support paginating over collections in a standardized way, defined by facebook's "),s("a",{attrs:{href:"https://relay.dev/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Relay GraphQL client"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("p",[t._v("The spec defines several types:")]),t._v(" "),s("ul",[s("li",[t._v("Connections - the paginated 1:N relationship itself")]),t._v(" "),s("li",[t._v("PageInfo - an object describing the pagination information of the current relation")]),t._v(" "),s("li",[t._v("Edge - a type describing each item in the pagination")]),t._v(" "),s("li",[t._v("Node - the type that's being paginated over")])]),t._v(" "),s("p",[t._v("An example query for a connection field looks something like this:")]),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 punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property-query"}},[t._v("queryName")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("first")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("after")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"cursor"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("pageInfo")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("hasNextPage")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("hasPreviousPage")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("startCursor")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("endCursor")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("edges")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("cursor")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("node")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("id")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# additional fields")]),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("The field can be paginated forwards by using "),s("code",[t._v("first")]),t._v(" (number of items) and "),s("code",[t._v("after")]),t._v(" (the current cursor), or backwards by using "),s("code",[t._v("last")]),t._v(" (number of items) and "),s("code",[t._v("before")]),t._v(" (the cursor).")]),t._v(" "),s("p",[t._v("Caliban ships with a set of abstract classes to make it easier to use Relay connections in your schema:")]),t._v(" "),s("div",{staticClass:"language-scala mdoc:silent extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("relay"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The entity you want to paginate over")]),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(" Item"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The specific edge type for your connection.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The default cursor implementation is a base64 encoded index offset,")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// but you can easily implement your own cursor to support e.g")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// cursor based pagination from your database.")]),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(" ItemEdge"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("cursor"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Base64Cursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" node"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Item"),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(" Edge"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Base64Cursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Item"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" ItemEdge "),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(" apply"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Item"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" i"),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(" ItemEdge "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ItemEdge"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Base64Cursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" x"),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 comment"}},[t._v("// The top level connection itself")]),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(" ItemConnection"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n pageInfo"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" PageInfo"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n edges"),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("ItemEdge"),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("extends")]),t._v(" Connection"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ItemEdge"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" ItemConnection "),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(" fromList "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Connection"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromList"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ItemConnection"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("apply"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ItemEdge"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("apply"),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 punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The arguments for your resolver.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// These are the minimal set of fields needed,")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// but you can easily customize it to add e.g")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// sorting or filtering.")]),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(" Args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n first"),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 last"),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 before"),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("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n after"),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("String")]),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("extends")]),t._v(" PaginationArgs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Base64Cursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\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(" Query"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("connection"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Args "),s("span",{pre:!0,attrs:{class:"token keyword"}},[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(" CalibanError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ItemConnection"),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("\n RootResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Query"),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("\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 pageInfo "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" Pagination"),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("\n items "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ItemConnection"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromList"),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("Item"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Item"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Item"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"3"')]),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(" pageInfo"),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(" items\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("h2",{attrs:{id:"cursors"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#cursors"}},[t._v("#")]),t._v(" Cursors")]),t._v(" "),s("p",[t._v("It's possible to implement your own cursor type to match with the underlying data source you have. This may be a database cursor, a date offset or something else which you use to efficiently filter your result set.")]),t._v(" "),s("p",[t._v("Start off by implementing a case class to represent your cursor:")]),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(" ElasticCursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),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("p",[t._v("To turn your case class into a usable cursor, you need to do two things: implement the "),s("code",[t._v("Cursor")]),t._v(" trait and specify a "),s("code",[t._v("Schema")]),t._v(" for the case class to make sure it's always serialized as a scalar value.")]),t._v(" "),s("p",[t._v("First, let's implement the trait:")]),t._v(" "),s("div",{staticClass:"language-scala mdoc:silent extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("java"),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("Base64\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[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("Try\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(" ElasticCursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),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("object")]),t._v(" ElasticCursor "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),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(" decoder "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Base64"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getDecoder"),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("lazy")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" encoder "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Base64"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getEncoder"),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("implicit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" cursor"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Cursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ElasticCursor"),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 keyword"}},[t._v("new")]),t._v(" Cursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ElasticCursor"),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("type")]),t._v(" T "),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 keyword"}},[t._v("def")]),t._v(" encode"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ElasticCursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),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 punctuation"}},[t._v("{")]),t._v("\n encoder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("encodeToString"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string-interpolation"}},[s("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"cursor:')]),s("span",{pre:!0,attrs:{class:"token interpolation"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),s("span",{pre:!0,attrs:{class:"token expression"}},[t._v("a"),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 string"}},[t._v('"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("getBytes"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"UTF-8"')]),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 keyword"}},[t._v("def")]),t._v(" decode"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),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(" Either"),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(" ElasticCursor"),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 Try"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n ElasticCursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),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("decoder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("decode"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),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 string"}},[t._v('"UTF-8"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("replaceFirst"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"cursor:"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toEither"),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("map"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toString"),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("def")]),t._v(" value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ElasticCursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" T "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" c"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value\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("and the schema:")]),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(" schema"),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(" ElasticCursor"),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("\n Cursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ElasticCursor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("encode\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/36.7450762f.js b/docs/assets/js/35.af875e74.js similarity index 99% rename from docs/assets/js/36.7450762f.js rename to docs/assets/js/35.af875e74.js index 6980a51d13..7434e42363 100644 --- a/docs/assets/js/36.7450762f.js +++ b/docs/assets/js/35.af875e74.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[36],{318:function(t,a,s){"use strict";s.r(a);var n=s(14),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"schema-comparison"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#schema-comparison"}},[t._v("#")]),t._v(" Schema comparison")]),t._v(" "),a("p",[t._v("The object "),a("code",[t._v("caliban.tools.SchemaComparison")]),t._v(" exposes a "),a("code",[t._v("compare")]),t._v(" function that compares 2 schemas from different origins. It takes 2 "),a("code",[t._v("SchemaLoader")]),t._v(" as arguments, which you can build with one of the following constructors:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("fromCaliban")]),t._v(": pass your "),a("code",[t._v("GraphQL")]),t._v(" object from Caliban")]),t._v(" "),a("li",[a("code",[t._v("fromFile")]),t._v(": pass the path to a file containing your schema in the GraphQL IDL")]),t._v(" "),a("li",[a("code",[t._v("fromString")]),t._v(": pass a string containing your schema in the GraphQL IDL")]),t._v(" "),a("li",[a("code",[t._v("fromIntrospection")]),t._v(": pass the URL of a GraphQL server supporting introspection")])]),t._v(" "),a("p",[t._v("The output of "),a("code",[t._v("compare")]),t._v(" is a "),a("code",[t._v("Task[List[SchemaComparisonChange]]")]),t._v(", with "),a("code",[t._v("SchemaComparisonChange")]),t._v(" being a sealed trait representing the various kinds of changes. "),a("code",[t._v("SchemaComparisonChange#breaking")]),t._v(" indicates if the change is breaking, such as removing a field or a type. "),a("code",[t._v("SchemaComparisonChange#toString")]),t._v(" will return a nice description of the change.")]),t._v(" "),a("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(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tools"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ZIO\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// schema from String")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),a("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"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// schema from Caliban")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" NameArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("pad"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),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(" Hero"),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(" NameArgs "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" nick"),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(" bday"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),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(" Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("hero"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Hero"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Hero"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"nick"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n diff "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" SchemaComparison"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("compare"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("SchemaLoader"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromString"),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(" SchemaLoader"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromCaliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("attempt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("println"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("diff"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mkString"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"\\n"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[35],{316:function(t,a,s){"use strict";s.r(a);var n=s(14),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"schema-comparison"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#schema-comparison"}},[t._v("#")]),t._v(" Schema comparison")]),t._v(" "),a("p",[t._v("The object "),a("code",[t._v("caliban.tools.SchemaComparison")]),t._v(" exposes a "),a("code",[t._v("compare")]),t._v(" function that compares 2 schemas from different origins. It takes 2 "),a("code",[t._v("SchemaLoader")]),t._v(" as arguments, which you can build with one of the following constructors:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("fromCaliban")]),t._v(": pass your "),a("code",[t._v("GraphQL")]),t._v(" object from Caliban")]),t._v(" "),a("li",[a("code",[t._v("fromFile")]),t._v(": pass the path to a file containing your schema in the GraphQL IDL")]),t._v(" "),a("li",[a("code",[t._v("fromString")]),t._v(": pass a string containing your schema in the GraphQL IDL")]),t._v(" "),a("li",[a("code",[t._v("fromIntrospection")]),t._v(": pass the URL of a GraphQL server supporting introspection")])]),t._v(" "),a("p",[t._v("The output of "),a("code",[t._v("compare")]),t._v(" is a "),a("code",[t._v("Task[List[SchemaComparisonChange]]")]),t._v(", with "),a("code",[t._v("SchemaComparisonChange")]),t._v(" being a sealed trait representing the various kinds of changes. "),a("code",[t._v("SchemaComparisonChange#breaking")]),t._v(" indicates if the change is breaking, such as removing a field or a type. "),a("code",[t._v("SchemaComparisonChange#toString")]),t._v(" will return a nice description of the change.")]),t._v(" "),a("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(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tools"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ZIO\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// schema from String")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),a("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"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// schema from Caliban")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" NameArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("pad"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),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(" Hero"),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(" NameArgs "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" nick"),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(" bday"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),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(" Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("hero"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Hero"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Hero"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"nick"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n diff "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" SchemaComparison"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("compare"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("SchemaLoader"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromString"),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(" SchemaLoader"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromCaliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("attempt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("println"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("diff"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mkString"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"\\n"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/36.86142689.js b/docs/assets/js/36.86142689.js new file mode 100644 index 0000000000..9b773ea3c8 --- /dev/null +++ b/docs/assets/js/36.86142689.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[36],{317:function(t,a,s){"use strict";s.r(a);var n=s(14),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"schema-reporting"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#schema-reporting"}},[t._v("#")]),t._v(" Schema Reporting")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("caliban-reporting")]),t._v(" module allows you to integrate with Apollo's "),a("a",{attrs:{href:"https://github.com/apollographql/apollo-schema-reporting-preview-docs/blob/master/schema-reporting-protocol.md",target:"_blank",rel:"noopener noreferrer"}},[t._v("schema reporting protocol"),a("OutboundLink")],1),t._v(".\nThis enables your servers to automatically publish updated schemas on start up without involving any additional tooling.")]),t._v(" "),a("p",[t._v("You can enable the settings by providing the "),a("code",[t._v("ReportingDaemon")]),t._v(" to your "),a("code",[t._v("Runtime")]),t._v(" during setup.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Define your GraphQL schema normally")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" \n graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Amos"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Define a SchemaReporter that will communicate with Apollo")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" reporterL "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" SchemaReporter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromDefaultConfig "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// Loads the access token from an environment variable called "APOLLO_KEY"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Or load it from a configuration type")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// val reporterL = ZLayer.service[ApolloConfig] >>> SchemaReporter.fromConfig[ApolloConfig](_.key)")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Define your graph references")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" daemon"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Scope "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("with")]),t._v(" ReportingDaemon"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n graph1 "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" SchemaReportingRef"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("make"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"my-graph@production"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// For dynamic or possibly updating schemas you can provide a Ref and a transform function that will allow")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// you to push schema updates that occur at runtime.")]),t._v("\n ref "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" Ref"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("make"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"schema { query: Query }\\n type Query { hello: String! }"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n graph2 "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" SchemaReportingRef"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromRef"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ref"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"dynamic-graph@production"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("identity"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ReportingDaemon"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("register"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("graph1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ReportingDaemon"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("register"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("graph2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Now wire it up")]),t._v("\nZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("scoped"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("daemon"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("provide"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("reporterL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" AsyncHttpClientZioBackend"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("layer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ReportingDaemon"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("live"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/37.9db4c004.js b/docs/assets/js/37.9db4c004.js deleted file mode 100644 index ea6f2d6dc4..0000000000 --- a/docs/assets/js/37.9db4c004.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[37],{317:function(t,a,s){"use strict";s.r(a);var n=s(14),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"schema-reporting"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#schema-reporting"}},[t._v("#")]),t._v(" Schema Reporting")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("caliban-reporting")]),t._v(" module allows you to integrate with Apollo's "),a("a",{attrs:{href:"https://www.apollographql.com/docs/studio/schema/schema-reporting-protocol/",target:"_blank",rel:"noopener noreferrer"}},[t._v("schema reporting protocol"),a("OutboundLink")],1),t._v(".\nThis enables your servers to automatically publish updated schemas on start up without involving any additional tooling.")]),t._v(" "),a("p",[t._v("You can enable the settings by providing the "),a("code",[t._v("ReportingDaemon")]),t._v(" to your "),a("code",[t._v("Runtime")]),t._v(" during setup.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Define your GraphQL schema normally")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" \n graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Amos"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Define a SchemaReporter that will communicate with Apollo")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" reporterL "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" SchemaReporter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromDefaultConfig "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// Loads the access token from an environment variable called "APOLLO_KEY"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Or load it from a configuration type")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// val reporterL = ZLayer.service[ApolloConfig] >>> SchemaReporter.fromConfig[ApolloConfig](_.key)")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Define your graph references")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" daemon"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Scope "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("with")]),t._v(" ReportingDaemon"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n graph1 "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" SchemaReportingRef"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("make"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("api"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"my-graph@production"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// For dynamic or possibly updating schemas you can provide a Ref and a transform function that will allow")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// you to push schema updates that occur at runtime.")]),t._v("\n ref "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" Ref"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("make"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"schema { query: Query }\\n type Query { hello: String! }"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n graph2 "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" SchemaReportingRef"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromRef"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ref"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"dynamic-graph@production"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("identity"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ReportingDaemon"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("register"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("graph1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ReportingDaemon"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("register"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("graph2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Now wire it up")]),t._v("\nZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("scoped"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("daemon"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("provide"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("reporterL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" AsyncHttpClientZioBackend"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("layer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ReportingDaemon"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("live"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/37.ebe3c9ba.js b/docs/assets/js/37.ebe3c9ba.js new file mode 100644 index 0000000000..611dfa6829 --- /dev/null +++ b/docs/assets/js/37.ebe3c9ba.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[37],{318:function(t,a,s){"use strict";s.r(a);var e=s(14),n=Object(e.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"schema-generation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#schema-generation"}},[t._v("#")]),t._v(" Schema generation")]),t._v(" "),a("p",[t._v("A GraphQL schema will be derived automatically at compile-time (no reflection) from the types present in your resolver.")]),t._v(" "),a("p",[t._v("If you're more interested in the schema-first approach, it is also possible to "),a("RouterLink",{attrs:{to:"/docs/server-codegen.html"}},[t._v("generate the Scala code from a GraphQL schema file")]),t._v(".")],1),t._v(" "),a("p",[t._v("The table below shows how common Scala types are converted to GraphQL types.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Scala Type")]),t._v(" "),a("th",[t._v("GraphQL Type")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[t._v("Boolean")]),t._v(" "),a("td",[t._v("Boolean")])]),t._v(" "),a("tr",[a("td",[t._v("Int")]),t._v(" "),a("td",[t._v("Int")])]),t._v(" "),a("tr",[a("td",[t._v("Float")]),t._v(" "),a("td",[t._v("Float")])]),t._v(" "),a("tr",[a("td",[t._v("Double")]),t._v(" "),a("td",[t._v("Float")])]),t._v(" "),a("tr",[a("td",[t._v("String")]),t._v(" "),a("td",[t._v("String")])]),t._v(" "),a("tr",[a("td",[t._v("java.util.UUID")]),t._v(" "),a("td",[t._v("ID")])]),t._v(" "),a("tr",[a("td",[t._v("Unit")]),t._v(" "),a("td",[t._v("Unit (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("Long")]),t._v(" "),a("td",[t._v("Long (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("BigInt")]),t._v(" "),a("td",[t._v("BigInt (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("BigDecimal")]),t._v(" "),a("td",[t._v("BigDecimal (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.Instant")]),t._v(" "),a("td",[t._v("Instant (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.LocalDate")]),t._v(" "),a("td",[t._v("LocalDate (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.LocalTime")]),t._v(" "),a("td",[t._v("LocalTime (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.LocalDateTime")]),t._v(" "),a("td",[t._v("LocalDateTime (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.OffsetDateTime")]),t._v(" "),a("td",[t._v("OffsetDateTime (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.ZonedDateTime")]),t._v(" "),a("td",[t._v("ZonedDateTime (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("Case Class")]),t._v(" "),a("td",[t._v("Object")])]),t._v(" "),a("tr",[a("td",[t._v("Sealed Trait")]),t._v(" "),a("td",[t._v("Enum, Union or Interface (see "),a("a",{attrs:{href:"#enums-unions-interfaces"}},[t._v("below")]),t._v(")")])]),t._v(" "),a("tr",[a("td",[t._v("Option[A]")]),t._v(" "),a("td",[t._v("Nullable A")])]),t._v(" "),a("tr",[a("td",[t._v("List[A]")]),t._v(" "),a("td",[t._v("List of A")])]),t._v(" "),a("tr",[a("td",[t._v("Set[A]")]),t._v(" "),a("td",[t._v("List of A")])]),t._v(" "),a("tr",[a("td",[t._v("Seq[A]")]),t._v(" "),a("td",[t._v("List of A")])]),t._v(" "),a("tr",[a("td",[t._v("Vector[A]")]),t._v(" "),a("td",[t._v("List of A")])]),t._v(" "),a("tr",[a("td",[t._v("A => B")]),t._v(" "),a("td",[t._v("A and B")])]),t._v(" "),a("tr",[a("td",[t._v("(A, B)")]),t._v(" "),a("td",[t._v("Object with 2 fields "),a("code",[t._v("_1")]),t._v(" and "),a("code",[t._v("_2")])])]),t._v(" "),a("tr",[a("td",[t._v("Either[A, B]")]),t._v(" "),a("td",[t._v("Object with 2 nullable fields "),a("code",[t._v("left")]),t._v(" and "),a("code",[t._v("right")])])]),t._v(" "),a("tr",[a("td",[t._v("Map[A, B]")]),t._v(" "),a("td",[t._v("List of Object with 2 fields "),a("code",[t._v("key")]),t._v(" and "),a("code",[t._v("value")])])]),t._v(" "),a("tr",[a("td",[t._v("ZIO[R, Nothing, A]")]),t._v(" "),a("td",[t._v("A")])]),t._v(" "),a("tr",[a("td",[t._v("ZIO[R, Throwable, A]")]),t._v(" "),a("td",[t._v("Nullable A")])]),t._v(" "),a("tr",[a("td",[t._v("Future[A]")]),t._v(" "),a("td",[t._v("Nullable A")])]),t._v(" "),a("tr",[a("td",[t._v("ZStream[R, Throwable, A]")]),t._v(" "),a("td",[t._v("A (subscription) or List of A (query, mutation)")])]),t._v(" "),a("tr",[a("td",[t._v("Json (from "),a("a",{attrs:{href:"https://github.com/circe/circe",target:"_blank",rel:"noopener noreferrer"}},[t._v("Circe"),a("OutboundLink")],1),t._v(")")]),t._v(" "),a("td",[t._v("Json (custom scalar, need "),a("code",[t._v("import caliban.interop.circe.json._")]),t._v(")")])]),t._v(" "),a("tr",[a("td",[t._v("Json (from "),a("a",{attrs:{href:"https://github.com/playframework/play-json",target:"_blank",rel:"noopener noreferrer"}},[t._v("play-json"),a("OutboundLink")],1),t._v(")")]),t._v(" "),a("td",[t._v("Json (custom scalar, need "),a("code",[t._v("import caliban.interop.play.json._")]),t._v(")")])])])]),t._v(" "),a("p",[t._v("See the "),a("a",{attrs:{href:"#custom-types"}},[t._v("Custom Types")]),t._v(" section to find out how to support your own types.")]),t._v(" "),a("p",[t._v("If you want Caliban to support other standard types, feel free to "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/issues",target:"_blank",rel:"noopener noreferrer"}},[t._v("file an issue"),a("OutboundLink")],1),t._v(" or even a PR.")]),t._v(" "),a("h2",{attrs:{id:"enums-unions-interfaces"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#enums-unions-interfaces"}},[t._v("#")]),t._v(" Enums, unions, interfaces")]),t._v(" "),a("p",[t._v("A sealed trait will be converted to a different GraphQL type depending on its content:")]),t._v(" "),a("ul",[a("li",[t._v("a sealed trait with only case objects will be converted to an "),a("code",[t._v("ENUM")])]),t._v(" "),a("li",[t._v("a sealed trait with only case classes will be converted to a "),a("code",[t._v("UNION")])])]),t._v(" "),a("p",[t._v('GraphQL does not support empty objects, so in case a sealed trait mixes case classes and case objects, a union type will be created and the case objects will have a "fake" field named '),a("code",[t._v("_")]),t._v(" which is not queryable.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Origin\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Origin "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" EARTH "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" MARS "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" BELT "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("The snippet above will produce the following GraphQL type:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("enum")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("BELT")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("EARTH")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("MARS")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Here's an example of union:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Role\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Role "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Captain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("shipName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Engineer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("specialty"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Mechanic "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("The snippet above will produce the following GraphQL type:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("union")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Role")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Captain")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Engineer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Mechanic")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Captain")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("shipName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Engineer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("specialty")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mechanic")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("Boolean")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("If your type needs to be shared between multiple unions you can use the "),a("code",[t._v("@GQLValueType")]),t._v(" annotation to have caliban\nproxy to another type beyond the sealed trait.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Pilot"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("callSign"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Role\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Role "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Captain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("shipName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Engineer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("specialty"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLValueType")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Proxy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("pilot"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Pilot"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("This will produce the following GraphQL Types:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("union")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Role")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Captain")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Engineer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Pilot")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Captain")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("shipName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Engineer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("specialty")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Pilot")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("callSign")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("If you prefer an "),a("code",[t._v("Interface")]),t._v(" instead of a "),a("code",[t._v("Union")]),t._v(" type, add the "),a("code",[t._v("@GQLInterface")]),t._v(" annotation to your sealed trait.\nAn interface will be created with all the fields that are common to the case classes extending the sealed trait, as long as they return the same type.")]),t._v(" "),a("p",[t._v("If you prefer to have a "),a("code",[t._v("Union")]),t._v(" type instead of an "),a("code",[t._v("Enum")]),t._v(", even when the sealed trait contains only objects, add the "),a("code",[t._v("@GQLUnion")]),t._v(" annotation.")]),t._v(" "),a("h2",{attrs:{id:"case-classes-and-sealed-traits"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#case-classes-and-sealed-traits"}},[t._v("#")]),t._v(" Case classes and sealed traits")]),t._v(" "),a("p",[t._v("The transformation between Scala types and GraphQL types is handled by a typeclass named "),a("code",[t._v("Schema")]),t._v(". As mentioned earlier, Caliban provides instances of "),a("code",[t._v("Schema")]),t._v(" for all basic Scala types, but inevitably you will need to support your own types, in particular case classes and sealed traits.")]),t._v(" "),a("p",[t._v("Caliban is able to generate instances of "),a("code",[t._v("Schema")]),t._v(" for case classes and sealed traits. You have two choices for doing that: auto derivation and semi-auto derivation.")]),t._v(" "),a("h3",{attrs:{id:"auto-derivation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#auto-derivation"}},[t._v("#")]),t._v(" Auto derivation")]),t._v(" "),a("p",[t._v("Auto derivation is achieved easily by adding the following import:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n")])])]),a("p",[t._v("Using this import, Caliban will generate "),a("code",[t._v("Schema")]),t._v(" instances for all the case classes and sealed traits that are found inside your resolver.")]),t._v(" "),a("div",{staticClass:"custom-block warning"},[a("p",{staticClass:"custom-block-title"},[t._v("Limitations")]),t._v(" "),a("p",[t._v("Auto derivation is the easiest way to get started, but it has some drawbacks:")]),t._v(" "),a("ul",[a("li",[t._v("If a type is referenced in several places inside your resolver, a "),a("code",[t._v("Schema")]),t._v(" will be generated for each occurrence, which can lead to longer compilation times and a high amount of generated code (a sign of this is that the compiler will suggest increasing "),a("code",[t._v("-Xmax-inlines")]),t._v(" in Scala 3).")]),t._v(" "),a("li",[t._v("When a "),a("code",[t._v("Schema")]),t._v(" is missing for a nested type inside your resolver, it can sometimes be difficult to find out which type is missing when using auto derivation, because the error message will mention the root type and not the nested one.")]),t._v(" "),a("li",[t._v("The macro that generates the "),a("code",[t._v("Schema")]),t._v(" instances sometimes gets confused when there are a lot of nested or recursive types, and can mistakenly generate a "),a("code",[t._v("Schema")]),t._v(" for types that already have a "),a("code",[t._v("Schema")]),t._v(" in scope. For this reason, semi-auto derivation is recommended for non-trivial schemas.")])])]),t._v(" "),a("h3",{attrs:{id:"semi-auto-derivation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#semi-auto-derivation"}},[t._v("#")]),t._v(" Semi-auto derivation")]),t._v(" "),a("p",[t._v("Semi-auto derivation is achieved as follows for each type that needs a "),a("code",[t._v("Schema")]),t._v(" instance ("),a("code",[t._v("MyClass")]),t._v(" in the example):")]),t._v(" "),a("code-group",[a("code-block",{attrs:{title:"Scala 2",active:""}},[a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schemaForMyClass"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3"}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SemiAuto\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if you don't want to use the `derives` syntax, you can also use the following:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])])])],1),t._v(" "),a("p",[t._v("In Scala 3, derivation doesn't support value classes and opaque types. You can use "),a("code",[t._v("Schema.genDebug")]),t._v(" to print the generated code in the console.")]),t._v(" "),a("h3",{attrs:{id:"combining-auto-and-semi-auto-derivation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#combining-auto-and-semi-auto-derivation"}},[t._v("#")]),t._v(" Combining auto and semi-auto derivation")]),t._v(" "),a("p",[t._v("For some types such as enums, it might be desirable to use auto derivation to reduce boilerplate schema definitions:")]),t._v(" "),a("code-group",[a("code-block",{attrs:{title:"Scala 2",active:""}},[a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Origin\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Origin "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" EARTH "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" MARS "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" BELT "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schemaForMyClass"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3 (Any schema)"}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("enum")]),t._v(" Origin "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Auto "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" EARTH"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MARS"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" BELT\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if you don't want to use the `derives` syntax, you can also use the following:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("derived\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3 (Custom schema)"}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" MyEnv\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" EnvSchema "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("enum")]),t._v(" Origin "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" EnvSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Auto "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" EARTH"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MARS"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" BELT\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if you don't want to use the `derives` syntax:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" EnvSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("derived\n")])])])])],1),t._v(" "),a("h3",{attrs:{id:"deriving-fields-from-case-class-methods-scala-3-only"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#deriving-fields-from-case-class-methods-scala-3-only"}},[t._v("#")]),t._v(" Deriving fields from case class methods (Scala 3 only)")]),t._v(" "),a("p",[t._v("In certain cases, your type might contain fields whose value depends on other fields. For example, you might have a "),a("code",[t._v("Person")]),t._v(" type with a "),a("code",[t._v("fullName")]),t._v(" field that is derived from the "),a("code",[t._v("firstName")]),t._v(" and "),a("code",[t._v("lastName")]),t._v(" fields. In this case, you can use the "),a("code",[t._v("@GQLField")]),t._v(" annotation to indicate that the field should be derived from the method with the same name.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Annotations"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("GQLField\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Person"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n firstName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n lastName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SemiAuto "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLField")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" fullName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("firstName")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v(" ")]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("lastName")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("This case class will generate the following GraphQL type:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Person")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("firstName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("lastName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("fullName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("The methods annotated with "),a("code",[t._v("@GQLField")]),t._v(" can return any type for which a "),a("code",[t._v("Schema")]),t._v(" is defined for, including effects such as "),a("code",[t._v("ZIO")]),t._v(" and "),a("code",[t._v("ZQuery")]),t._v(".\nIn addition, you can use any other annotation that is supported for case class arguments, such as "),a("code",[t._v("@GQLName")]),t._v(", "),a("code",[t._v("@GQLDescription")]),t._v(" and "),a("code",[t._v("@GQLDeprecated")]),t._v(".")]),t._v(" "),a("div",{staticClass:"custom-block warning"},[a("p",{staticClass:"custom-block-title"},[t._v("Caveats")]),t._v(" "),a("p",[t._v("Derivation of fields via the "),a("code",[t._v("@GQLField")]),t._v(" annotation can be convenient in certain cases, but has the following limitations:")]),t._v(" "),a("ul",[a("li",[t._v("The method cannot take arguments. If you need to derive a field that requires arguments, you can return a function instead.")]),t._v(" "),a("li",[t._v("The method must be public (i.e. not "),a("code",[t._v("private")]),t._v(" or "),a("code",[t._v("protected")]),t._v(").")]),t._v(" "),a("li",[t._v("It currently only works with methods (i.e., "),a("code",[t._v("def")]),t._v("). If you need to cache the output of the method, you can create a private lazy val and return it from the method.")]),t._v(" "),a("li",[t._v("It is not compatible with ahead-of-time compilation (e.g., generating a GraalVM native-image executable).")])])]),t._v(" "),a("h2",{attrs:{id:"arguments"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#arguments"}},[t._v("#")]),t._v(" Arguments")]),t._v(" "),a("p",[t._v("To declare a field that take arguments, create a dedicated case class representing the arguments and make the field a "),a("em",[t._v("function")]),t._v(" from this class to the result type.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" origin"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" FilterArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("origin"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FilterArgs "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("The snippet above will produce the following GraphQL type:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Queries")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("characters")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("origin")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Caliban provides auto-derivation for common types such as "),a("code",[t._v("Int")]),t._v(", "),a("code",[t._v("String")]),t._v(", "),a("code",[t._v("List")]),t._v(", "),a("code",[t._v("Option")]),t._v(", etc. but you can also support your own types by providing an implicit instance of "),a("code",[t._v("ArgBuilder")]),t._v(" that defines how incoming arguments from that types should be extracted. You also need a "),a("code",[t._v("Schema")]),t._v(" for those types.")]),t._v(" "),a("p",[t._v("Derivation of "),a("code",[t._v("ArgBuilder")]),t._v(" for case classes works similarly to "),a("code",[t._v("Schema")]),t._v(" derivation. You can use auto derivation by adding the following import:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n")])])]),a("p",[t._v("Or you can use semi-auto derivation as follows:")]),t._v(" "),a("code-group",[a("code-block",{attrs:{title:"Scala 2",active:""}},[a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" argBuilderForMyClass"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schemaForMyClass"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3"}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SemiAuto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ArgBuilder\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if you don't want to use the `derives` syntax, you can also use the following:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])])])],1),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[t._v("There is no "),a("code",[t._v("ArgBuilder")]),t._v(" for tuples. If you have multiple arguments, use a case class containing all of them instead of a tuple.")])]),t._v(" "),a("h2",{attrs:{id:"custom-types"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#custom-types"}},[t._v("#")]),t._v(" Custom types")]),t._v(" "),a("p",[t._v("Caliban provides auto-derivation for common types such as "),a("code",[t._v("Int")]),t._v(", "),a("code",[t._v("String")]),t._v(", "),a("code",[t._v("List")]),t._v(", "),a("code",[t._v("Option")]),t._v(", etc. but you can also support your own types by providing an implicit instance of "),a("code",[t._v("Schema")]),t._v(". Note that you don't have to do this if your types are just case classes composed of common types.")]),t._v(" "),a("p",[t._v("An easy way to do this is to reuse existing instances and use "),a("code",[t._v("contramap")]),t._v(" to map from your type to the original type. Here's an example of creating an instance for "),a("a",{attrs:{href:"https://github.com/fthomas/refined",target:"_blank",rel:"noopener noreferrer"}},[t._v("refined"),a("OutboundLink")],1),t._v("'s "),a("code",[t._v("NonEmptyString")]),t._v(" reusing existing instance for "),a("code",[t._v("String")]),t._v(" (if you use "),a("code",[t._v("refined")]),t._v(", you might want to look at "),a("a",{attrs:{href:"https://github.com/niqdev/caliban-extras#caliban-refined",target:"_blank",rel:"noopener noreferrer"}},[t._v("caliban-refined"),a("OutboundLink")],1),t._v("):")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" nonEmptyStringSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" NonEmptyString"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" \n Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("stringSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("contramap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("You can also use the "),a("code",[t._v("scalarSchema")]),t._v(" helper to create your own scalar types, providing a name, an optional description, and a function from your type to a "),a("code",[t._v("ResponseValue")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ResponseValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ObjectValue\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" unitSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("scalarSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Unit"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ObjectValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Nil"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("If you are using a custom type as part of the input you also have to provide an implicit instance of "),a("code",[t._v("ArgBuilder")]),t._v(". For example here's how to do that for "),a("code",[t._v("java.time.LocalDate")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("java"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("time"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("LocalDate\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("scala"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("util"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Try\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Value\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ExecutionError\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" localDateArgBuilder"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("LocalDate"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" Value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n Try"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("LocalDate"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fold"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ex "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" Left"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"Can't parse ")]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("value")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v(' into a LocalDate"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" innerThrowable "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ex"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Right"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" other "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" Left"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"Can't build a LocalDate from input ")]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("other")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Value classes ("),a("code",[t._v("case class SomeWrapper(self: SomeType) extends AnyVal")]),t._v(") will be unwrapped by default in Scala 2 (this is not supported by Scala 3 derivation).")]),t._v(" "),a("h2",{attrs:{id:"effects"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#effects"}},[t._v("#")]),t._v(" Effects")]),t._v(" "),a("p",[t._v("Fields can return ZIO effects. This allows you to leverage all the features provided by ZIO: timeouts, retries, access to ZIO environment, memoizing, etc. An effect will be run every time a query requiring the corresponding field is executed.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" CharacterName "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CharacterName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n character"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CharacterName "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" RIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Console"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("If you don't use ZIO environment ("),a("code",[t._v("R")]),t._v(" = "),a("code",[t._v("Any")]),t._v("), there is nothing special to do to get it working.")]),t._v(" "),a("p",[t._v("If you require a ZIO environment and use Scala 2, you can't use "),a("code",[t._v("Schema.gen")]),t._v(" or the import we saw previously because they expect "),a("code",[t._v("R")]),t._v(" to be "),a("code",[t._v("Any")]),t._v(". Instead, you need to make a new object that extends "),a("code",[t._v("caliban.schema.GenericSchema[R]")]),t._v(" for your custom "),a("code",[t._v("R")]),t._v(". Then you can use "),a("code",[t._v("gen")]),t._v(" or "),a("code",[t._v("auto")]),t._v(" from that object to generate your schema.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" MyEnv "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Console \n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" customSchema "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" GenericSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("customSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if you use semi-auto generation, use this instead:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// implicit val characterSchema: Schema[MyEnv, Character] = customSchema.gen")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// implicit val queriesSchema: Schema[MyEnv, Queries] = customSchema.gen")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" queries "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("attempt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("If you require a ZIO environment and use Scala 3, things are simpler since you don't need "),a("code",[t._v("GenericSchema")]),t._v(". Just make sure to use "),a("code",[t._v("Schema.gen")]),t._v(" with the proper R type parameter.\nTo make sure Caliban uses the proper environment, you need to specify it explicitly to "),a("code",[t._v("graphQL(...)")]),t._v(", unless you already have "),a("code",[t._v("Schema")]),t._v(" instances for your root operations in scope.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" queries "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("attempt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// implicit val queriesSchema: Schema[MyEnv, Queries] = Schema.gen")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// val api = graphQL(RootResolver(queries)) // it will infer MyEnv thanks to the instance above")]),t._v("\n")])])]),a("h2",{attrs:{id:"annotations"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#annotations"}},[t._v("#")]),t._v(" Annotations")]),t._v(" "),a("p",[t._v("Caliban supports a few annotations to enrich data types:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v('@GQLName("name")')]),t._v(" allows you to specify a different name for a data type or a field.")]),t._v(" "),a("li",[a("code",[t._v('@GQLInputName("name")')]),t._v(" allows you to specify a different name for a data type used as an input (by default, the suffix "),a("code",[t._v("Input")]),t._v(" is appended to the type name).")]),t._v(" "),a("li",[a("code",[t._v('@GQLDescription("description")')]),t._v(" lets you provide a description for a data type or field. This description will be visible when your schema is introspected.")]),t._v(" "),a("li",[a("code",[t._v('@GQLDeprecated("reason")')]),t._v(" allows deprecating a field or an enum value.")]),t._v(" "),a("li",[a("code",[t._v("@GQLExcluded")]),t._v(" allows you to hide a field from the generated schema.")]),t._v(" "),a("li",[a("code",[t._v("@GQLInterface")]),t._v(" to force a sealed trait generating an interface instead of a union.")]),t._v(" "),a("li",[a("code",[t._v("@GQLDirective(directive: Directive)")]),t._v(" to add a directive to a field or type.")]),t._v(" "),a("li",[a("code",[t._v("@GQLValueType(isScalar)")]),t._v(" forces a type to behave as a value type for derivation. Meaning that caliban will ignore the outer type and take the first case class parameter as the real type. If "),a("code",[t._v("isScalar")]),t._v(" is true, it will generate a scalar named after the case class (default: false).")]),t._v(" "),a("li",[a("code",[t._v('@GQLDefault("defaultValue")')]),t._v(" allows you to specify a default value for an input field using GraphQL syntax. The default value will be visible in your schema's SDL and during introspection.")])]),t._v(" "),a("h2",{attrs:{id:"java-8-time-types"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#java-8-time-types"}},[t._v("#")]),t._v(" Java 8 Time types")]),t._v(" "),a("p",[t._v("Caliban provides implicit "),a("code",[t._v("Schema")]),t._v(" types for the standard "),a("code",[t._v("java.time")]),t._v(" types, by default these will use the\nISO standard strings for serialization and deserialization. However, you can customize this behavior by using\nexplicit constructor available under the "),a("code",[t._v("ArgBuilder")]),t._v(" companion object. For instance, you can specify an "),a("code",[t._v("instantEpoch")]),t._v("\nto handle instants which are encoded using a "),a("code",[t._v("Long")]),t._v(" from the standard java epoch time (January 1st 1970 00:00:00).\nFor some time formats you can also specify a specific "),a("code",[t._v("DateTimeFormatter")]),t._v(" to handle your particular date time needs.")]),t._v(" "),a("h2",{attrs:{id:"building-schemas-by-hand"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#building-schemas-by-hand"}},[t._v("#")]),t._v(" Building Schemas by hand")]),t._v(" "),a("p",[t._v("Sometimes for whatever reason schema generation fails. This can happen if your schema has co-recursive types and derivation is unable\nto generate a schema for them. In cases like these you may need to instead create your own schema by hand.")]),t._v(" "),a("p",[t._v("Consider the case where you have three types which create cyclical dependencies on one another")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("UIO\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" users"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("User"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" parent"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" organization"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Organization"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Organization"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" groups"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" User"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" group"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("These three types all depend on one another and if you attempt to generate a schema from them you will either end up with compiler errors or you will end up with a nasty runtime\nerror from a "),a("code",[t._v("NullPointerException")]),t._v(". To help the compiler out we can hand generate the types for these case classes instead.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("obj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" groupSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" obj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Group"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"A group of users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" ft "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("users"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"parent"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parent"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"organization"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("organization"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" orgSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Organization"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" obj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Organization"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"An organization of groups"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" ft "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"groups"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("groups"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" userSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" User"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" obj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"User"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"A user of the service"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" ft "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"group"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])],1)}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/38.47b0ded6.js b/docs/assets/js/38.47b0ded6.js deleted file mode 100644 index 1f071bd42a..0000000000 --- a/docs/assets/js/38.47b0ded6.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[38],{319:function(t,a,s){"use strict";s.r(a);var e=s(14),n=Object(e.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"schemas"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#schemas"}},[t._v("#")]),t._v(" Schemas")]),t._v(" "),a("p",[t._v("A GraphQL schema will be derived automatically at compile-time (no reflection) from the types present in your resolver.\nThe table below shows how common Scala types are converted to GraphQL types.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Scala Type")]),t._v(" "),a("th",[t._v("GraphQL Type")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[t._v("Boolean")]),t._v(" "),a("td",[t._v("Boolean")])]),t._v(" "),a("tr",[a("td",[t._v("Int")]),t._v(" "),a("td",[t._v("Int")])]),t._v(" "),a("tr",[a("td",[t._v("Float")]),t._v(" "),a("td",[t._v("Float")])]),t._v(" "),a("tr",[a("td",[t._v("Double")]),t._v(" "),a("td",[t._v("Float")])]),t._v(" "),a("tr",[a("td",[t._v("String")]),t._v(" "),a("td",[t._v("String")])]),t._v(" "),a("tr",[a("td",[t._v("java.util.UUID")]),t._v(" "),a("td",[t._v("ID")])]),t._v(" "),a("tr",[a("td",[t._v("Unit")]),t._v(" "),a("td",[t._v("Unit (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("Long")]),t._v(" "),a("td",[t._v("Long (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("BigInt")]),t._v(" "),a("td",[t._v("BigInt (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("BigDecimal")]),t._v(" "),a("td",[t._v("BigDecimal (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.Instant")]),t._v(" "),a("td",[t._v("Instant (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.LocalDate")]),t._v(" "),a("td",[t._v("LocalDate (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.LocalTime")]),t._v(" "),a("td",[t._v("LocalTime (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.LocalDateTime")]),t._v(" "),a("td",[t._v("LocalDateTime (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.OffsetDateTime")]),t._v(" "),a("td",[t._v("OffsetDateTime (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("java.time.ZonedDateTime")]),t._v(" "),a("td",[t._v("ZonedDateTime (custom scalar)")])]),t._v(" "),a("tr",[a("td",[t._v("Case Class")]),t._v(" "),a("td",[t._v("Object")])]),t._v(" "),a("tr",[a("td",[t._v("Sealed Trait")]),t._v(" "),a("td",[t._v("Enum or Union")])]),t._v(" "),a("tr",[a("td",[t._v("Option[A]")]),t._v(" "),a("td",[t._v("Nullable A")])]),t._v(" "),a("tr",[a("td",[t._v("List[A]")]),t._v(" "),a("td",[t._v("List of A")])]),t._v(" "),a("tr",[a("td",[t._v("Set[A]")]),t._v(" "),a("td",[t._v("List of A")])]),t._v(" "),a("tr",[a("td",[t._v("Seq[A]")]),t._v(" "),a("td",[t._v("List of A")])]),t._v(" "),a("tr",[a("td",[t._v("Vector[A]")]),t._v(" "),a("td",[t._v("List of A")])]),t._v(" "),a("tr",[a("td",[t._v("A => B")]),t._v(" "),a("td",[t._v("A and B")])]),t._v(" "),a("tr",[a("td",[t._v("(A, B)")]),t._v(" "),a("td",[t._v("Object with 2 fields "),a("code",[t._v("_1")]),t._v(" and "),a("code",[t._v("_2")])])]),t._v(" "),a("tr",[a("td",[t._v("Either[A, B]")]),t._v(" "),a("td",[t._v("Object with 2 nullable fields "),a("code",[t._v("left")]),t._v(" and "),a("code",[t._v("right")])])]),t._v(" "),a("tr",[a("td",[t._v("Map[A, B]")]),t._v(" "),a("td",[t._v("List of Object with 2 fields "),a("code",[t._v("key")]),t._v(" and "),a("code",[t._v("value")])])]),t._v(" "),a("tr",[a("td",[t._v("ZIO[R, Nothing, A]")]),t._v(" "),a("td",[t._v("A")])]),t._v(" "),a("tr",[a("td",[t._v("ZIO[R, Throwable, A]")]),t._v(" "),a("td",[t._v("Nullable A")])]),t._v(" "),a("tr",[a("td",[t._v("Future[A]")]),t._v(" "),a("td",[t._v("Nullable A")])]),t._v(" "),a("tr",[a("td",[t._v("ZStream[R, Throwable, A]")]),t._v(" "),a("td",[t._v("A (subscription) or List of A (query, mutation)")])]),t._v(" "),a("tr",[a("td",[t._v("Json (from "),a("a",{attrs:{href:"https://github.com/circe/circe",target:"_blank",rel:"noopener noreferrer"}},[t._v("Circe"),a("OutboundLink")],1),t._v(")")]),t._v(" "),a("td",[t._v("Json (custom scalar, need "),a("code",[t._v("import caliban.interop.circe.json._")]),t._v(")")])]),t._v(" "),a("tr",[a("td",[t._v("Json (from "),a("a",{attrs:{href:"https://github.com/playframework/play-json",target:"_blank",rel:"noopener noreferrer"}},[t._v("play-json"),a("OutboundLink")],1),t._v(")")]),t._v(" "),a("td",[t._v("Json (custom scalar, need "),a("code",[t._v("import caliban.interop.play.json._")]),t._v(")")])])])]),t._v(" "),a("p",[t._v("See the "),a("a",{attrs:{href:"#custom-types"}},[t._v("Custom Types")]),t._v(" section to find out how to support your own types.")]),t._v(" "),a("p",[t._v("If you want Caliban to support other standard types, feel free to "),a("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/issues",target:"_blank",rel:"noopener noreferrer"}},[t._v("file an issue"),a("OutboundLink")],1),t._v(" or even a PR.")]),t._v(" "),a("h2",{attrs:{id:"enums-unions-interfaces"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#enums-unions-interfaces"}},[t._v("#")]),t._v(" Enums, unions, interfaces")]),t._v(" "),a("p",[t._v("A sealed trait will be converted to a different GraphQL type depending on its content:")]),t._v(" "),a("ul",[a("li",[t._v("a sealed trait with only case objects will be converted to an "),a("code",[t._v("ENUM")])]),t._v(" "),a("li",[t._v("a sealed trait with only case classes will be converted to a "),a("code",[t._v("UNION")])])]),t._v(" "),a("p",[t._v('GraphQL does not support empty objects, so in case a sealed trait mixes case classes and case objects, a union type will be created and the case objects will have a "fake" field named '),a("code",[t._v("_")]),t._v(" which is not queryable.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Origin\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Origin "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" EARTH "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" MARS "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" BELT "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("The snippet above will produce the following GraphQL type:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("enum")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("BELT")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("EARTH")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("MARS")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Here's an example of union:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Role\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Role "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Captain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("shipName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Engineer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("specialty"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Mechanic "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("The snippet above will produce the following GraphQL type:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("union")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Role")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Captain")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Engineer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Mechanic")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Captain")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("shipName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Engineer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("specialty")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mechanic")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("Boolean")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("If your type needs to be shared between multiple unions you can use the "),a("code",[t._v("@GQLValueType")]),t._v(" annotation to have caliban\nproxy to another type beyond the sealed trait.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Pilot"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("callSign"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Role\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Role "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Captain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("shipName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Engineer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("specialty"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Role\n \n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLValueType")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Proxy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("pilot"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Pilot"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("This will produce the following GraphQL Types:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("union")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Role")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Captain")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Engineer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v("Pilot")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Captain")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("shipName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Engineer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("specialty")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Pilot")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("callSign")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("If you prefer an "),a("code",[t._v("Interface")]),t._v(" instead of a "),a("code",[t._v("Union")]),t._v(" type, add the "),a("code",[t._v("@GQLInterface")]),t._v(" annotation to your sealed trait.\nAn interface will be created with all the fields that are common to the case classes extending the sealed trait, as long as they return the same type.")]),t._v(" "),a("p",[t._v("If you prefer to have a "),a("code",[t._v("Union")]),t._v(" type instead of an "),a("code",[t._v("Enum")]),t._v(", even when the sealed trait contains only objects, add the "),a("code",[t._v("@GQLUnion")]),t._v(" annotation.")]),t._v(" "),a("h2",{attrs:{id:"case-classes-and-sealed-traits"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#case-classes-and-sealed-traits"}},[t._v("#")]),t._v(" Case classes and sealed traits")]),t._v(" "),a("p",[t._v("The transformation between Scala types and GraphQL types is handled by a typeclass named "),a("code",[t._v("Schema")]),t._v(". As mentioned earlier, Caliban provides instances of "),a("code",[t._v("Schema")]),t._v(" for all basic Scala types, but inevitably you will need to support your own types, in particular case classes and sealed traits.")]),t._v(" "),a("p",[t._v("Caliban is able to generate instances of "),a("code",[t._v("Schema")]),t._v(" for case classes and sealed traits. You have two choices for doing that: auto derivation and semi-auto derivation.")]),t._v(" "),a("h3",{attrs:{id:"auto-derivation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#auto-derivation"}},[t._v("#")]),t._v(" Auto derivation")]),t._v(" "),a("p",[t._v("Auto derivation is achieved easily by adding the following import:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n")])])]),a("p",[t._v("Using this import, Caliban will generate "),a("code",[t._v("Schema")]),t._v(" instances for all the case classes and sealed traits that are found inside your resolver.")]),t._v(" "),a("div",{staticClass:"custom-block warning"},[a("p",{staticClass:"custom-block-title"},[t._v("Auto derivation limitations")]),t._v(" "),a("p",[t._v("Auto derivation is the easiest way to get started, but it has some drawbacks:")]),t._v(" "),a("ul",[a("li",[t._v("If a type is referenced in several places inside your resolver, a "),a("code",[t._v("Schema")]),t._v(" will be generated for each occurrence, which can lead to longer compilation times and a high amount of generated code (a sign of this is that the compiler will suggest increasing "),a("code",[t._v("-Xmax-inlines")]),t._v(" in Scala 3).")]),t._v(" "),a("li",[t._v("When a "),a("code",[t._v("Schema")]),t._v(" is missing for a nested type inside your resolver, it can sometimes be difficult to find out which type is missing when using auto derivation, because the error message will mention the root type and not the nested one.")]),t._v(" "),a("li",[t._v("The macro that generates the "),a("code",[t._v("Schema")]),t._v(" instances sometimes gets confused when there are a lot of nested or recursive types, and can mistakenly generate a "),a("code",[t._v("Schema")]),t._v(" for types that already have a "),a("code",[t._v("Schema")]),t._v(" in scope. For this reason, semi-auto derivation is recommended for non-trivial schemas.")])])]),t._v(" "),a("h3",{attrs:{id:"semi-auto-derivation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#semi-auto-derivation"}},[t._v("#")]),t._v(" Semi-auto derivation")]),t._v(" "),a("p",[t._v("Semi-auto derivation is achieved as follows for each type that needs a "),a("code",[t._v("Schema")]),t._v(" instance ("),a("code",[t._v("MyClass")]),t._v(" in the example):")]),t._v(" "),a("code-group",[a("code-block",{attrs:{title:"Scala 2",active:""}},[a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schemaForMyClass"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3"}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SemiAuto\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if you don't want to use the `derives` syntax, you can also use the following:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])])])],1),t._v(" "),a("p",[t._v("In Scala 3, derivation doesn't support value classes and opaque types. You can use "),a("code",[t._v("Schema.genDebug")]),t._v(" to print the generated code in the console.")]),t._v(" "),a("h3",{attrs:{id:"combining-auto-and-semi-auto-derivation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#combining-auto-and-semi-auto-derivation"}},[t._v("#")]),t._v(" Combining auto and semi-auto derivation")]),t._v(" "),a("p",[t._v("For some types such as enums, it might be desirable to use auto derivation to reduce boilerplate schema definitions:")]),t._v(" "),a("code-group",[a("code-block",{attrs:{title:"Scala 2",active:""}},[a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Origin\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Origin "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" EARTH "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" MARS "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" BELT "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Origin\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schemaForMyClass"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3 (Any schema)"}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("enum")]),t._v(" Origin "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Auto "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" EARTH"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MARS"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" BELT\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if you don't want to use the `derives` syntax, you can also use the following:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("derived\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3 (Custom schema)"}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" MyEnv\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" EnvSchema "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SchemaDerivation"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("enum")]),t._v(" Origin "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" EnvSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Auto "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" EARTH"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MARS"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" BELT\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if you don't want to use the `derives` syntax:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" EnvSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("derived\n")])])])])],1),t._v(" "),a("h3",{attrs:{id:"deriving-fields-from-case-class-methods-scala-3-only"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#deriving-fields-from-case-class-methods-scala-3-only"}},[t._v("#")]),t._v(" Deriving fields from case class methods (Scala 3 only)")]),t._v(" "),a("p",[t._v("In certain cases, your type might contain fields whose value depends on other fields. For example, you might have a "),a("code",[t._v("Person")]),t._v(" type with a "),a("code",[t._v("fullName")]),t._v(" field that is derived from the "),a("code",[t._v("firstName")]),t._v(" and "),a("code",[t._v("lastName")]),t._v(" fields. In this case, you can use the "),a("code",[t._v("@GQLField")]),t._v(" annotation to indicate that the field should be derived from the method with the same name.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Annotations"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("GQLField\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Person"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n firstName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n lastName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SemiAuto "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLField")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" fullName"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("firstName")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v(" ")]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("lastName")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("This case class will generate the following GraphQL type:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Person")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("firstName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("lastName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("fullName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("The methods annotated with "),a("code",[t._v("@GQLField")]),t._v(" can return any type for which a "),a("code",[t._v("Schema")]),t._v(" is defined for, including effects such as "),a("code",[t._v("ZIO")]),t._v(" and "),a("code",[t._v("ZQuery")]),t._v(".\nIn addition, you can use any other annotation that is supported for case class arguments, such as "),a("code",[t._v("@GQLName")]),t._v(", "),a("code",[t._v("@GQLDescription")]),t._v(" and "),a("code",[t._v("@GQLDeprecated")]),t._v(".")]),t._v(" "),a("div",{staticClass:"custom-block warning"},[a("p",{staticClass:"custom-block-title"},[t._v("Caveats")]),t._v(" "),a("p",[t._v("Derivation of fields via the "),a("code",[t._v("@GQLField")]),t._v(" annotation can be convenient in certain cases, but has the following limitations:")]),t._v(" "),a("ul",[a("li",[t._v("The method cannot take arguments. If you need to derive a field that requires arguments, you can return a function instead.")]),t._v(" "),a("li",[t._v("The method must be public (i.e. not "),a("code",[t._v("private")]),t._v(" or "),a("code",[t._v("protected")]),t._v(").")]),t._v(" "),a("li",[t._v("It currently only works with methods (i.e., "),a("code",[t._v("def")]),t._v("). If you need to cache the output of the method, you can create a private lazy val and return it from the method.")]),t._v(" "),a("li",[t._v("It is not compatible with ahead-of-time compilation (e.g., generating a GraalVM native-image executable).")])])]),t._v(" "),a("h2",{attrs:{id:"arguments"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#arguments"}},[t._v("#")]),t._v(" Arguments")]),t._v(" "),a("p",[t._v("To declare a field that take arguments, create a dedicated case class representing the arguments and make the field a "),a("em",[t._v("function")]),t._v(" from this class to the result type.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" origin"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" FilterArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("origin"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Origin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FilterArgs "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("The snippet above will produce the following GraphQL type:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Queries")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("characters")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("origin")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Origin")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Character")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Caliban provides auto-derivation for common types such as "),a("code",[t._v("Int")]),t._v(", "),a("code",[t._v("String")]),t._v(", "),a("code",[t._v("List")]),t._v(", "),a("code",[t._v("Option")]),t._v(", etc. but you can also support your own types by providing an implicit instance of "),a("code",[t._v("caliban.schema.ArgBuilder")]),t._v(" that defines how incoming arguments from that types should be extracted. You also need a "),a("code",[t._v("Schema")]),t._v(" for those types.")]),t._v(" "),a("p",[t._v("Derivation of "),a("code",[t._v("ArgBuilder")]),t._v(" for case classes works similarly to "),a("code",[t._v("Schema")]),t._v(" derivation. You can use auto derivation by adding the following import, or via the "),a("code",[t._v("derives")]),t._v(" keyword (Scala 3 only):")]),t._v(" "),a("code-group",[a("code-block",{attrs:{title:"Scala 2",active:""}},[a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3"}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" FieldArg"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FieldArg"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("GenAuto\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if you don't want to use the `derives` syntax, you can also use the following:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("GenAuto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("derived\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("derived\n")])])])])],1),t._v(" "),a("p",[t._v("Or you can use semi-auto derivation as follows:")]),t._v(" "),a("code-group",[a("code-block",{attrs:{title:"Scala 2",active:""}},[a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" argBuilderForMyClass"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schemaForMyClass"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])])]),t._v(" "),a("code-block",{attrs:{title:"Scala 3"}},[a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("derives")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SemiAuto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ArgBuilder\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if you don't want to use the `derives` syntax, you can also use the following:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("given")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyClass"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])])])],1),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[t._v("There is no "),a("code",[t._v("ArgBuilder")]),t._v(" for tuples. If you have multiple arguments, use a case class containing all of them instead of a tuple.")])]),t._v(" "),a("h2",{attrs:{id:"custom-types"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#custom-types"}},[t._v("#")]),t._v(" Custom types")]),t._v(" "),a("p",[t._v("Caliban provides auto-derivation for common types such as "),a("code",[t._v("Int")]),t._v(", "),a("code",[t._v("String")]),t._v(", "),a("code",[t._v("List")]),t._v(", "),a("code",[t._v("Option")]),t._v(", etc. but you can also support your own types by providing an implicit instance of "),a("code",[t._v("caliban.schema.Schema")]),t._v(". Note that you don't have to do this if your types are just case classes composed of common types.")]),t._v(" "),a("p",[t._v("An easy way to do this is to reuse existing instances and use "),a("code",[t._v("contramap")]),t._v(" to map from your type to the original type. Here's an example of creating an instance for "),a("a",{attrs:{href:"https://github.com/fthomas/refined",target:"_blank",rel:"noopener noreferrer"}},[t._v("refined"),a("OutboundLink")],1),t._v("'s "),a("code",[t._v("NonEmptyString")]),t._v(" reusing existing instance for "),a("code",[t._v("String")]),t._v(" (if you use "),a("code",[t._v("refined")]),t._v(", you might want to look at "),a("a",{attrs:{href:"https://github.com/niqdev/caliban-extras#caliban-refined",target:"_blank",rel:"noopener noreferrer"}},[t._v("caliban-refined"),a("OutboundLink")],1),t._v("):")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" nonEmptyStringSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" NonEmptyString"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("stringSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("contramap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("You can also use the "),a("code",[t._v("scalarSchema")]),t._v(" helper to create your own scalar types, providing a name, an optional description, and a function from your type to a "),a("code",[t._v("ResponseValue")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ResponseValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ObjectValue\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" unitSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("scalarSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Unit"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ObjectValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Nil"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("If you are using a custom type as part of the input you also have to provide an implicit instance of "),a("code",[t._v("caliban.schema.ArgBuilder")]),t._v(". For example here's how to do that for "),a("code",[t._v("java.time.LocalDate")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("java"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("time"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("LocalDate\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("scala"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("util"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Try\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Value\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ExecutionError\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" localDateArgBuilder"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("LocalDate"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" Value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n Try"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("LocalDate"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parse"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fold"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ex "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" Left"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"Can't parse ")]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("value")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v(' into a LocalDate"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" innerThrowable "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ex"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Right"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" other "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" Left"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"Can't build a LocalDate from input ")]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("other")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Value classes ("),a("code",[t._v("case class SomeWrapper(self: SomeType) extends AnyVal")]),t._v(") will be unwrapped by default in Scala 2 (this is not supported by Scala 3 derivation).")]),t._v(" "),a("h2",{attrs:{id:"effects"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#effects"}},[t._v("#")]),t._v(" Effects")]),t._v(" "),a("p",[t._v("Fields can return ZIO effects. This allows you to leverage all the features provided by ZIO: timeouts, retries, access to ZIO environment, memoizing, etc. An effect will be run every time a query requiring the corresponding field is executed.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent:reset extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" CharacterName "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CharacterName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("characters"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n character"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" CharacterName "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" RIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Console"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Character"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("If you don't use ZIO environment ("),a("code",[t._v("R")]),t._v(" = "),a("code",[t._v("Any")]),t._v("), there is nothing special to do to get it working.")]),t._v(" "),a("p",[t._v("If you require a ZIO environment and use Scala 2, you can't use "),a("code",[t._v("Schema.gen")]),t._v(" or the import we saw previously because they expect "),a("code",[t._v("R")]),t._v(" to be "),a("code",[t._v("Any")]),t._v(". Instead, you need to make a new object that extends "),a("code",[t._v("caliban.schema.GenericSchema[R]")]),t._v(" for your custom "),a("code",[t._v("R")]),t._v(". Then you can use "),a("code",[t._v("gen")]),t._v(" or "),a("code",[t._v("auto")]),t._v(" from that object to generate your schema.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" MyEnv "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Console \n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" customSchema "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" GenericSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("customSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if you use semi-auto generation, use this instead:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// implicit val characterSchema: Schema[MyEnv, Character] = customSchema.gen")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// implicit val queriesSchema: Schema[MyEnv, Queries] = customSchema.gen")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" queries "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("attempt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("If you require a ZIO environment and use Scala 3, things are simpler since you don't need "),a("code",[t._v("GenericSchema")]),t._v(". Just make sure to use "),a("code",[t._v("Schema.gen")]),t._v(" with the proper R type parameter.\nTo make sure Caliban uses the proper environment, you need to specify it explicitly to "),a("code",[t._v("graphQL(...)")]),t._v(", unless you already have "),a("code",[t._v("Schema")]),t._v(" instances for your root operations in scope.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" queries "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("attempt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _ "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ZIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("succeed"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("MyEnv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("queries"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// implicit val queriesSchema: Schema[MyEnv, Queries] = Schema.gen")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// val api = graphQL(RootResolver(queries)) // it will infer MyEnv thanks to the instance above")]),t._v("\n")])])]),a("h2",{attrs:{id:"annotations"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#annotations"}},[t._v("#")]),t._v(" Annotations")]),t._v(" "),a("p",[t._v("Caliban supports a few annotations to enrich data types:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v('@GQLName("name")')]),t._v(" allows you to specify a different name for a data type or a field.")]),t._v(" "),a("li",[a("code",[t._v('@GQLInputName("name")')]),t._v(" allows you to specify a different name for a data type used as an input (by default, the suffix "),a("code",[t._v("Input")]),t._v(" is appended to the type name).")]),t._v(" "),a("li",[a("code",[t._v('@GQLDescription("description")')]),t._v(" lets you provide a description for a data type or field. This description will be visible when your schema is introspected.")]),t._v(" "),a("li",[a("code",[t._v('@GQLDeprecated("reason")')]),t._v(" allows deprecating a field or an enum value.")]),t._v(" "),a("li",[a("code",[t._v("@GQLExcluded")]),t._v(" allows you to hide a field from the generated schema.")]),t._v(" "),a("li",[a("code",[t._v("@GQLInterface")]),t._v(" to force a sealed trait generating an interface instead of a union.")]),t._v(" "),a("li",[a("code",[t._v("@GQLDirective(directive: Directive)")]),t._v(" to add a directive to a field or type.")]),t._v(" "),a("li",[a("code",[t._v("@GQLValueType(isScalar)")]),t._v(" forces a type to behave as a value type for derivation. Meaning that caliban will ignore the outer type and take the first case class parameter as the real type. If "),a("code",[t._v("isScalar")]),t._v(" is true, it will generate a scalar named after the case class (default: false).")]),t._v(" "),a("li",[a("code",[t._v('@GQLDefault("defaultValue")')]),t._v(" allows you to specify a default value for an input field using GraphQL syntax. The default value will be visible in your schema's SDL and during introspection.")])]),t._v(" "),a("h2",{attrs:{id:"java-8-time-types"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#java-8-time-types"}},[t._v("#")]),t._v(" Java 8 Time types")]),t._v(" "),a("p",[t._v("Caliban provides implicit "),a("code",[t._v("Schema")]),t._v(" types for the standard "),a("code",[t._v("java.time")]),t._v(" types, by default these will use the\nISO standard strings for serialization and deserialization. However, you can customize this behavior by using\nexplicit constructor available under the "),a("code",[t._v("ArgBuilder")]),t._v(" companion object. For instance, you can specify an "),a("code",[t._v("instantEpoch")]),t._v("\nto handle instants which are encoded using a "),a("code",[t._v("Long")]),t._v(" from the standard java epoch time (January 1st 1970 00:00:00).\nFor some time formats you can also specify a specific "),a("code",[t._v("DateTimeFormatter")]),t._v(" to handle your particular date time needs.")]),t._v(" "),a("h2",{attrs:{id:"code-generation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#code-generation"}},[t._v("#")]),t._v(" Code generation")]),t._v(" "),a("p",[t._v("Caliban can automatically generate Scala code from a GraphQL schema.")]),t._v(" "),a("p",[t._v("In order to use this feature, add the "),a("code",[t._v("caliban-codegen-sbt")]),t._v(" sbt plugin to your "),a("code",[t._v("project/plugins.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("addSbtPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-codegen-sbt"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("And enable it in your "),a("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("enablePlugins"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CalibanPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("Then call the "),a("code",[t._v("calibanGenSchema")]),t._v(" sbt command.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("calibanGenSchema schemaPath outputPath "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("scalafmtPath path"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("headers name"),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("name2"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("value2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("packageName name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("effect fqdn"),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(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("scalarMappings gqlType"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("q"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("d"),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("Type"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("gqlType2"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("q"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("d"),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("Type2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("imports a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("c"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("c"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("d"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("E"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("abstractEffectType "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\ncalibanGenSchema project"),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("graphql src"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("main"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("MyAPI"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("scala\n")])])]),a("p",[t._v("This command will create a Scala file in "),a("code",[t._v("outputPath")]),t._v(" containing all the types defined in the provided GraphQL schema defined at "),a("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(" "),a("p",[t._v("The generated code will be formatted with Scalafmt using the configuration defined by "),a("code",[t._v("--scalafmtPath")]),t._v(" option (default: "),a("code",[t._v(".scalafmt.conf")]),t._v("). If you provide a URL for "),a("code",[t._v("schemaPath")]),t._v(", you can provide request headers with "),a("code",[t._v("--headers")]),t._v(" option.")]),t._v(" "),a("p",[t._v("The package of the generated code is derived from the folder of "),a("code",[t._v("outputPath")]),t._v(". This can be overridden by providing an alternative package with the "),a("code",[t._v("--packageName")]),t._v(" option.")]),t._v(" "),a("p",[t._v("By default, each Query and Mutation will be wrapped into a "),a("code",[t._v("zio.UIO")]),t._v(" effect. This can be overridden by providing an alternative effect with the "),a("code",[t._v("--effect")]),t._v(" option.")]),t._v(" "),a("p",[t._v("You can also indicate that the effect type is abstract via "),a("code",[t._v("--abstractEffectType true")]),t._v(", in which case "),a("code",[t._v("Query")]),t._v(" will be replaced by "),a("code",[t._v("Query[F[_]]")]),t._v(" and so on (note "),a("code",[t._v("F")]),t._v(" will be used unless "),a("code",[t._v("--effect ")]),t._v(" is explicitly given in which case "),a("code",[t._v("")]),t._v(" would be used in place of "),a("code",[t._v("F")]),t._v(").")]),t._v(" "),a("p",[t._v("By default the suffix "),a("code",[t._v("Input")]),t._v(" is appended to the type name of input types in the derived schema. Use the "),a("code",[t._v("--preserveInputNames")]),t._v(" flag to disable this.")]),t._v(" "),a("p",[t._v("If you use scala3, you can enable "),a("code",[t._v("--addDerives")]),t._v(" flag to automatically add "),a("code",[t._v("derives")]),t._v(" clauses to the generated code. It will add type class instance derivation that create schema.")]),t._v(" "),a("p",[t._v("In case you use derives and ZIO Environment other than Any, you need to pass type info or your schema generation will fail. Use the "),a("code",[t._v("--envForDerives")]),t._v(" flag to\npass in the type alias for your ZIO Environment.")]),t._v(" "),a("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"),a("code",[t._v("--scalarMappings")]),t._v(" option. Also you can add additional imports by providing "),a("code",[t._v("--imports")]),t._v(" option.")]),t._v(" "),a("p",[t._v("Since Caliban 1.3.0, you can generate schemas using an sbt "),a("code",[t._v("sourceGenerator")]),t._v(", which means your schemas will be generated every time you compile (or when you import your build into "),a("a",{attrs:{href:"https://scalameta.org/metals/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Metals"),a("OutboundLink")],1),t._v(").\nThis can be configured with the same settings as "),a("RouterLink",{attrs:{to:"/docs/client.html#code-generation"}},[t._v("the client generators")]),t._v(", but you have to specify "),a("code",[t._v(".genType(Codegen.GenType.Schema)")]),t._v(" in the "),a("code",[t._v("calibanSettings")]),t._v(" entry for a given file.")],1),t._v(" "),a("h2",{attrs:{id:"building-schemas-by-hand"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#building-schemas-by-hand"}},[t._v("#")]),t._v(" Building Schemas by hand")]),t._v(" "),a("p",[t._v("Sometimes for whatever reason schema generation fails. This can happen if your schema has co-recursive types and 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(" "),a("p",[t._v("Consider the case where you have three types which create cyclical dependencies on one another")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("UIO\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" users"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("User"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" parent"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" organization"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Organization"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Organization"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" groups"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" User"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" group"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("These three types all depend on one another and if you attempt to generate a schema from them you will either end up with compiler errors or you will end up with a nasty runtime\nerror from a "),a("code",[t._v("NullPointerException")]),t._v(". To help the compiler out we can hand generate the types for these case classes instead.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("obj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" groupSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" obj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Group"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"A group of users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" ft "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"users"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("users"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"parent"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parent"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"organization"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("organization"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" orgSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Organization"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" obj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Organization"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"An organization of groups"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" ft "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"groups"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("groups"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" userSchema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" User"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" obj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"User"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"A user of the service"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" ft "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n field"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"group"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("group"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])],1)}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/38.81bab45a.js b/docs/assets/js/38.81bab45a.js new file mode 100644 index 0000000000..fddd1d9920 --- /dev/null +++ b/docs/assets/js/38.81bab45a.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[38],{319:function(t,a,s){"use strict";s.r(a);var n=s(14),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"code-generation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#code-generation"}},[t._v("#")]),t._v(" Code generation")]),t._v(" "),a("p",[t._v("If you want a workflow where you first edit a GraphQL schema file, and then generate type-safe server stubs, Caliban has your back.")]),t._v(" "),a("p",[t._v("You'll first need to add the following dependency to your "),a("code",[t._v("project/plugins.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("addSbtPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-codegen-sbt"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("You then enable it in your "),a("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" _root_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tools"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Codegen\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" myproject "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" project\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// enable caliban codegen plugin")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("enablePlugins"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CalibanPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("settings"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// add code generation settings")]),t._v("\n Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" caliban "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" calibanSettings "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Seq"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n calibanSetting"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"myproject/src/main/graphql/myapi.graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// important to set this, otherwise you'll get client code")]),t._v("\n _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("genType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Codegen"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("GenType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// you can customize the codegen further with this DSL")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("clientName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"NameOfApi.scala"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("packageName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"myproject.mypackage"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("You can also generate it manually using the following sbt command:")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("calibanGenSchema schemaPath outputPath [options]\n")])])]),a("p",[t._v("Example:")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("calibanGenSchema project/schema.graphql src/main/MyAPI.scala --addDerives true\n")])])]),a("h2",{attrs:{id:"options"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#options"}},[t._v("#")]),t._v(" Options")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("scalafmtPath")]),t._v(": Specifies the configuration file for Scalafmt. Default: "),a("code",[t._v(".scalafmt.conf")]),t._v(".")]),t._v(" "),a("li",[a("code",[t._v("headers")]),t._v(": Provides request headers when "),a("code",[t._v("schemaPath")]),t._v(" is a URL.")]),t._v(" "),a("li",[a("code",[t._v("packageName")]),t._v(": Overrides the package name derived from the folder of "),a("code",[t._v("outputPath")]),t._v(".")]),t._v(" "),a("li",[a("code",[t._v("effect")]),t._v(": Overrides the default effect ("),a("code",[t._v("zio.UIO")]),t._v(") for wrapping fields in Queries and Mutations.")]),t._v(" "),a("li",[a("code",[t._v("scalarMappings")]),t._v(": Forces a mapping between a GraphQL type and a Scala class (e.g., scalars).")]),t._v(" "),a("li",[a("code",[t._v("imports")]),t._v(": Adds additional imports to the generated code.")]),t._v(" "),a("li",[a("code",[t._v("abstractEffectType")]),t._v(": Indicates that the effect type is abstract. Fields in Queries and Mutations will return "),a("code",[t._v("F[_]")]),t._v(".")]),t._v(" "),a("li",[a("code",[t._v("preserveInputNames")]),t._v(": Disables the default behavior of appending "),a("code",[t._v("Input")]),t._v(" to the type name of input types in the derived schema.")]),t._v(" "),a("li",[a("code",[t._v("addDerives")]),t._v(": Adds "),a("code",[t._v("derives")]),t._v(" clauses for type class instance derivation in Scala 3.")]),t._v(" "),a("li",[a("code",[t._v("envForDerives")]),t._v(": Specifies the type alias for your ZIO Environment when using "),a("code",[t._v("derives")]),t._v(" and a ZIO Environment other than "),a("code",[t._v("Any")]),t._v(".")])]),t._v(" "),a("h2",{attrs:{id:"lazy-evaluation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#lazy-evaluation"}},[t._v("#")]),t._v(" Lazy evaluation")]),t._v(" "),a("p",[t._v("The main difference between generating code for client usage and for server usage is that on the server you need to account for\ncode which should only be evaluated if the client requests the field!")]),t._v(" "),a("p",[t._v("You can annotate this directly in the graphql schema by creating a "),a("code",[t._v("@lazy")]),t._v(" directive.")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("directive")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("on")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("FIELD_DEFINITION")]),t._v("\n")])])]),a("p",[t._v("You can then annotate fields in the graphql schema like this:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("directive")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("on")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("FIELD_DEFINITION")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyType")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("myLazyField")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@lazy")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("myField")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("And you'll get a case class which looks something like this:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("myLazyField"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" myField"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("When implementing this, "),a("code",[t._v("myLazyField")]),t._v(" will only be evaluated if the client requested it in the query")]),t._v(" "),a("h2",{attrs:{id:"newtype-declaration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#newtype-declaration"}},[t._v("#")]),t._v(" Newtype declaration")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("@newtype")]),t._v(" directive in caliban allows you to wrap your GraphQL fields into statically\ntyped IDs for backend. For clients, they can use the GraphQL as before and do not\nhave to adjust their typing, or optionally can generate stronger typed IDs using\nthe directive.")]),t._v(" "),a("p",[t._v("In the following example we want to encapsulate "),a("code",[t._v("id : ID")]),t._v(" as FooId for better type safety, so\nwe use the "),a("code",[t._v("@newtype")]),t._v(" directive on the "),a("code",[t._v("Query")]),t._v(" and Foo object type.\nOn mutation, we are passing an optional field of String. To avoid mixing with other String\ntypes in backend code we decided to create a "),a("code",[t._v("@newtype")]),t._v(" of Bar instead.")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("directive")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@newtype")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("on")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("FIELD_DEFINITION")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("ARGUMENT_DEFINITION")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("INPUT_FIELD_DEFINITION")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Query")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property-query"}},[t._v("getFoo")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("id")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("ID")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@newtype")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"FooId"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Foo")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mutation")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("updateFoo")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("foo")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token atom-input class-name"}},[t._v("FooInput")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Foo")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Foo")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("id")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("ID")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@newtype")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"FooId"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("input")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token atom-input class-name"}},[t._v("FooInput")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("maybeBar")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@newtype")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bar"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("With Scalar mapping for ID set to Int, it would give you the following case classes.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("AnyVal")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("AnyVal")]),t._v("\n")])])]),a("p",[t._v("The "),a("code",[t._v("extends AnyVal")]),t._v(" ensures type erasure in such a way that we do not have to consider this abstraction\non client side, and hence graphql query remains the same as before applying the directive.\nBut for this to work we need to supply some implicit for our schema to understand the AnyVal\nconversion and mapping of the return values using "),a("code",[t._v("@GQLDirective")]),t._v(" annotation.")]),t._v(" "),a("p",[t._v("With this in place our generate type code should look something like this:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Types "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" QueryGetFooArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MutationUpdateFooArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("foo"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FooInput"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("AnyVal")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Bar "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" implicitly"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("contramap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" argBuilder"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" implicitly"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("AnyVal")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" FooId "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" implicitly"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("contramap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" argBuilder"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" implicitly"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Foo"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLDirective")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Directive"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"newtype"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"FooId"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FooId\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" FooInput"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLDirective")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Directive"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"newtype"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bar"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n maybeBar"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" scala"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/39.956f0096.js b/docs/assets/js/39.956f0096.js deleted file mode 100644 index 5b2954c252..0000000000 --- a/docs/assets/js/39.956f0096.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[39],{320:function(t,a,s){"use strict";s.r(a);var n=s(14),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"server-code-generation-from-schema"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#server-code-generation-from-schema"}},[t._v("#")]),t._v(" Server code generation from schema")]),t._v(" "),a("p",[t._v("If you want a workflow where you first edit a graphql schema file, and then generate type-safe server stubs, Caliban has your back.")]),t._v(" "),a("p",[t._v("You'll first need to add the following dependency to your "),a("code",[t._v("project/plugins.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[t._v("addSbtPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-codegen-sbt"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.3.1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("You then enable it in your "),a("code",[t._v("build.sbt")]),t._v(" file:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" _root_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("tools"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Codegen\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" myproject "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" project\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// enable caliban codegen plugin")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("enablePlugins"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CalibanPlugin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("settings"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n scalaVersion "),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('"3.3.3"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n libraryDependencies "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// the exact list of dependencies will vary with the libraries you want")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.3.1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-http4s"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.3.1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-cats"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.3.1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.softwaremill.sttp.tapir"')]),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('"tapir-json-circe"')]),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.7.5"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"org.http4s"')]),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('"http4s-ember-server"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0.23.19"')]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Compile "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" caliban "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" calibanSettings "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Seq"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n calibanSetting"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"myproject/src/main/graphql/myapi.graphql"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// important to set this. otherwise you'll get client code")]),t._v("\n _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("genType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Codegen"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("GenType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// you can customize the codegen further with this DSL")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("clientName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"NameOfApi.scala"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("packageName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"myproject.mypackage"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h3",{attrs:{id:"lazy-evaluation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#lazy-evaluation"}},[t._v("#")]),t._v(" Lazy evaluation")]),t._v(" "),a("p",[t._v("The main difference between generating code for client usage and for server usage is that on the server you need to account for\ncode which should only be evaluated if the client requests the field!")]),t._v(" "),a("p",[t._v("You can annotate this directly in the graphql schema by creating a "),a("code",[t._v("@lazy")]),t._v(" directive.")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("directive")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("on")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("FIELD_DEFINITION")]),t._v("\n")])])]),a("p",[t._v("You can then annotate fields in the graphql schema like this:")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("directive")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@lazy")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("on")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("FIELD_DEFINITION")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyType")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("myLazyField")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@lazy")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("myField")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("And you'll get a case class which looks something like this:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MyType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("myLazyField"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" zio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("UIO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" myField"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("When implementing this, "),a("code",[t._v("myLazyField")]),t._v(" will only be evaluated if the client requested it in the query")]),t._v(" "),a("h3",{attrs:{id:"newtype-declaration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#newtype-declaration"}},[t._v("#")]),t._v(" Newtype declaration")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("@newtype")]),t._v(" directive in caliban allows you to wrap your GraphQL fields into statically\ntyped IDs for backend. For clients, they can use the GraphQL as before and do not\nhave to adjust their typing, or optionally can generate stronger typed IDs using\nthe directive.")]),t._v(" "),a("p",[t._v("In the following example we want to encapsulate "),a("code",[t._v("id : ID")]),t._v(" as FooId for better type safety, so\nwe use the "),a("code",[t._v("@newtype")]),t._v(" directive on the "),a("code",[t._v("Query")]),t._v(" and Foo object type.\nOn mutation, we are passing an optional field of String. To avoid mixing with other String\ntypes in backend code we decided to create a "),a("code",[t._v("@newtype")]),t._v(" of Bar instead.")]),t._v(" "),a("div",{staticClass:"language-graphql extra-class"},[a("pre",{pre:!0,attrs:{class:"language-graphql"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("directive")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@newtype")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("on")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("FIELD_DEFINITION")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("ARGUMENT_DEFINITION")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("INPUT_FIELD_DEFINITION")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Query")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property-query"}},[t._v("getFoo")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("id")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("ID")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@newtype")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"FooId"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Foo")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mutation")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("updateFoo")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("foo")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token atom-input class-name"}},[t._v("FooInput")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Foo")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Foo")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("id")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("ID")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@newtype")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"FooId"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("input")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token atom-input class-name"}},[t._v("FooInput")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("maybeBar")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token scalar"}},[t._v("String")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token directive function"}},[t._v("@newtype")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bar"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("With Scalar mapping for ID set to Int, it would give you the following case classes.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("AnyVal")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("AnyVal")]),t._v("\n")])])]),a("p",[t._v("The "),a("code",[t._v("extends AnyVal")]),t._v(" ensures type erasure in such a way that we do not have to consider this abstraction\non client side, and hence graphql query remains the same as before applying the directive.\nBut for this to work we need to supply some implicit for our schema to understand the AnyVal\nconversion and mapping of the return values using "),a("code",[t._v("@GQLDirective")]),t._v(" annotation.")]),t._v(" "),a("p",[t._v("With this in place our generate type code should look something like this:")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Types "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" QueryGetFooArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" MutationUpdateFooArgs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("foo"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FooInput"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("AnyVal")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Bar "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" implicitly"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("contramap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" argBuilder"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" implicitly"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("AnyVal")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" FooId "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" schema"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" implicitly"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("contramap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" argBuilder"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" implicitly"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ArgBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("FooId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Foo"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLDirective")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Directive"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"newtype"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"FooId"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n id"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" FooId\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" FooInput"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLDirective")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Directive"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"newtype"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bar"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n maybeBar"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" scala"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Bar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/40.f2a62c0d.js b/docs/assets/js/39.d3af0fd1.js similarity index 99% rename from docs/assets/js/40.f2a62c0d.js rename to docs/assets/js/39.d3af0fd1.js index a1ccd4fb4a..cd2c90a57e 100644 --- a/docs/assets/js/40.f2a62c0d.js +++ b/docs/assets/js/39.d3af0fd1.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[40],{321:function(t,s,a){"use strict";a.r(s);var n=a(14),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"stitching"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#stitching"}},[t._v("#")]),t._v(" Stitching")]),t._v(" "),s("p",[s("strong",[t._v("Stitching")]),t._v(" is a part of "),s("code",[t._v("caliban-tools")]),t._v(" which can be used to use parts of another GraphQL API from an API you're building in situations where using Apollo federation isn't an option. You can also use it to fully subsume and proxy another GraphQL schema.")]),t._v(" "),s("p",[t._v("In general, Federation should be your preferred choice.")]),t._v(" "),s("p",[t._v("You should also be careful when using stitching since it's very easy to pull in large parts of an external schema's types and structure into your API. This can make it error prone since the likelihood that you'll get type clashes between your API and the API you're stitching in quickly increases.")]),t._v(" "),s("h2",{attrs:{id:"dependencies"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#dependencies"}},[t._v("#")]),t._v(" Dependencies")]),t._v(" "),s("p",[t._v("In order to use stitching, add "),s("code",[t._v("caliban-tools")]),t._v(" to your dependencies:")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-tools"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v("\n")])])]),s("h2",{attrs:{id:"stitching-in-action"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#stitching-in-action"}},[t._v("#")]),t._v(" Stitching in Action")]),t._v(" "),s("p",[t._v("Let's start out by defining our API. We'll have "),s("code",[t._v("AppUser")]),t._v(" profiles, that has a linked "),s("code",[t._v("featuredRepository")]),t._v(". For the "),s("code",[t._v("featuredRepository")]),t._v(", we want to leverage "),s("a",{attrs:{href:"https://docs.github.com/en/graphql",target:"_blank",rel:"noopener noreferrer"}},[t._v("Github's GraphQL API"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("div",{staticClass:"language-scala mdoc:silent extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" StitchingExample "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" GenericSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" AppUser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" name"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" featuredRepository"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" name"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" GetUserQuery"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" repository"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GetUser"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GetUserQuery "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" UIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("AppUser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n RootResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GetUser "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" query "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n Random"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nextUUID"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("uuid "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n AppUser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n id "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" uuid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toString"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n name "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" query"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n featuredRepository "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("query"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" query"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("Now let's integrate with the Github API!")]),t._v(" "),s("p",[t._v("In order to do this we're going to do a couple of things:")]),t._v(" "),s("ol",[s("li",[t._v("Load the introspection schema from Github's API")]),t._v(" "),s("li",[t._v("Parse the introspected schema into a "),s("code",[t._v("caliban.introspection.adt.__Schema")])]),t._v(" "),s("li",[t._v("Use the parsed schema to generate an "),s("code",[t._v("implicit Schema[R, A]")]),t._v(" for the entities we're stitching. This effectively replaces our own schema with one from Github.")]),t._v(" "),s("li",[t._v("Teach our implicit schema how to map our local resolver to a query that can be resolved remotely by calling Github's API.")])]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" GITHUB_API "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https://api.github.com/graphql"')]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n sttpClient "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ZIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("environment"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("SttpClient"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 1")]),t._v("\n schemaLoader "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" SchemaLoader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromIntrospection"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GITHUB_API"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n schema "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" schemaLoader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("load\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 2")]),t._v("\n remoteSchema "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ZIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromOption"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RemoteSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parseRemoteSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n remoteSchemaResolvers "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" RemoteSchemaResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("remoteSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 3")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" githubProfileSchema"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n remoteSchemaResolvers\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("remoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Repository"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 4")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Here we need to translate our local `Repository` case class into")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// a top-level query which can be issued towards Github's API.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We do this by accepting a `caliban.execution.Field`, representing")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// all the selected fields for a repository and map that to the")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// top-level `repository` query in the Github API.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This means the final query will end up looking something like this:")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// query {")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// repository(owner: r.args.owner, name: r.args.name) {")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// . ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// }")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// }")]),t._v("\n RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromFunction"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ResolveRequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n name "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"repository"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n arguments "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Map"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"owner"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" Value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" Value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromUrl"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GITHUB_API"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("provide"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sttpClient"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("However, when running this we will experience failing requests due to "),s("code",[t._v("401 Unauthorized")]),t._v(". This is because all queries to Github's API requires authorization to be provided. In order to fix this, we need to add authorization to both the introspection query as well as our remote resolver. We also need a config module that can provide us with a Github token based on the value of "),s("code",[t._v("GITHUB_TOKEN")]),t._v(" in our environment.")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Configuration"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("githubToken"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Configuration "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" fromEnvironment "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n githubToken "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" read"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GITHUB_TOKEN"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" Configuration"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("githubToken"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toLayer\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" read"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Task"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Task"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("effect"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n sys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("env"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("We can now update the introspection query to use our token:")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n config "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ZIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("environment"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Has"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Configuration"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n schemaLoader "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" SchemaLoader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromIntrospection"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GITHUB_API"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Options"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Authorization"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string-interpolation"}},[s("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bearer ')]),s("span",{pre:!0,attrs:{class:"token interpolation"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),s("span",{pre:!0,attrs:{class:"token expression"}},[t._v("config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("get"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("githubToken")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")])]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n")])])]),s("p",[t._v("as well as update our resolver to authorize our request.")]),t._v(" "),s("p",[t._v("In order to do this, we can use "),s("code",[t._v("RemoteResolver[R, E, A, B]")]),t._v(" which lets us compose resolution steps via "),s("code",[t._v(">>>")]),t._v(".")]),t._v(" "),s("p",[t._v("In order to make this code easier, we can extract the mechanics around sending the actual request:")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" apiRequest "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toQuery "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GITHUB_API"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromFunctionM"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" HttpRequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n config "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ZIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("service"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Configuration"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Authorization"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-interpolation"}},[s("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bearer ')]),s("span",{pre:!0,attrs:{class:"token interpolation"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),s("span",{pre:!0,attrs:{class:"token expression"}},[t._v("config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("githubToken")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")])]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("execute "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("unwrap\n")])])]),s("p",[t._v("And now we can use our new "),s("code",[t._v("apiRequest")]),t._v(" when resolving our "),s("code",[t._v("Schema[ZEnv, Repository]")]),t._v(":")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" githubProfileSchema"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n remoteSchemaResolvers\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("remoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Repository"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromFunction"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ResolveRequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n name "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"repository"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n arguments "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Map"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"owner"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" Value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" Value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" apiRequest\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("provide"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sttpClient "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("All that's left to do is to hook up to an HTTP server and configure a Github API token. And now you have an API that can handle queries such as these:")]),t._v(" "),s("div",{staticClass:"language-graphql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-graphql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("query")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property-query"}},[t._v("GetUser")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ghostdogpr"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("repository")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("id")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("name")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("featuredRepository")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property-query"}},[t._v("pullRequests")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("states")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("OPEN")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("first")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("edges")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("node")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("title")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("author")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("login")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("See the "),s("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/stitching",target:"_blank",rel:"noopener noreferrer"}},[t._v("examples directory"),s("OutboundLink")],1),t._v(" for a full example.")]),t._v(" "),s("h2",{attrs:{id:"things-not-yet-supported"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#things-not-yet-supported"}},[t._v("#")]),t._v(" Things not yet supported")]),t._v(" "),s("ul",[s("li",[t._v("Type renaming.")]),t._v(" "),s("li",[t._v("Type conflict resolution strategies.")])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[39],{320:function(t,s,a){"use strict";a.r(s);var n=a(14),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"stitching"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#stitching"}},[t._v("#")]),t._v(" Stitching")]),t._v(" "),s("p",[s("strong",[t._v("Stitching")]),t._v(" is a part of "),s("code",[t._v("caliban-tools")]),t._v(" which can be used to use parts of another GraphQL API from an API you're building in situations where using Apollo federation isn't an option. You can also use it to fully subsume and proxy another GraphQL schema.")]),t._v(" "),s("p",[t._v("In general, Federation should be your preferred choice.")]),t._v(" "),s("p",[t._v("You should also be careful when using stitching since it's very easy to pull in large parts of an external schema's types and structure into your API. This can make it error prone since the likelihood that you'll get type clashes between your API and the API you're stitching in quickly increases.")]),t._v(" "),s("h2",{attrs:{id:"dependencies"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#dependencies"}},[t._v("#")]),t._v(" Dependencies")]),t._v(" "),s("p",[t._v("In order to use stitching, add "),s("code",[t._v("caliban-tools")]),t._v(" to your dependencies:")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-tools"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v("\n")])])]),s("h2",{attrs:{id:"stitching-in-action"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#stitching-in-action"}},[t._v("#")]),t._v(" Stitching in Action")]),t._v(" "),s("p",[t._v("Let's start out by defining our API. We'll have "),s("code",[t._v("AppUser")]),t._v(" profiles, that has a linked "),s("code",[t._v("featuredRepository")]),t._v(". For the "),s("code",[t._v("featuredRepository")]),t._v(", we want to leverage "),s("a",{attrs:{href:"https://docs.github.com/en/graphql",target:"_blank",rel:"noopener noreferrer"}},[t._v("Github's GraphQL API"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("div",{staticClass:"language-scala mdoc:silent extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("ArgBuilder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("zio"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" StitchingExample "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" GenericSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" AppUser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" name"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" featuredRepository"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" name"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" GetUserQuery"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" repository"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GetUser"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GetUserQuery "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" UIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("AppUser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" GraphQL"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n RootResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Queries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GetUser "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" query "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n Random"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nextUUID"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("map"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("uuid "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n AppUser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n id "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" uuid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toString"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n name "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" query"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n featuredRepository "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("query"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" query"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("Now let's integrate with the Github API!")]),t._v(" "),s("p",[t._v("In order to do this we're going to do a couple of things:")]),t._v(" "),s("ol",[s("li",[t._v("Load the introspection schema from Github's API")]),t._v(" "),s("li",[t._v("Parse the introspected schema into a "),s("code",[t._v("caliban.introspection.adt.__Schema")])]),t._v(" "),s("li",[t._v("Use the parsed schema to generate an "),s("code",[t._v("implicit Schema[R, A]")]),t._v(" for the entities we're stitching. This effectively replaces our own schema with one from Github.")]),t._v(" "),s("li",[t._v("Teach our implicit schema how to map our local resolver to a query that can be resolved remotely by calling Github's API.")])]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" GITHUB_API "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https://api.github.com/graphql"')]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n sttpClient "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ZIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("environment"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("SttpClient"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 1")]),t._v("\n schemaLoader "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" SchemaLoader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromIntrospection"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GITHUB_API"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n schema "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" schemaLoader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("load\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 2")]),t._v("\n remoteSchema "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ZIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromOption"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RemoteSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("parseRemoteSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n remoteSchemaResolvers "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" RemoteSchemaResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("remoteSchema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 3")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" githubProfileSchema"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n remoteSchemaResolvers\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("remoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Repository"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 4")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Here we need to translate our local `Repository` case class into")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// a top-level query which can be issued towards Github's API.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We do this by accepting a `caliban.execution.Field`, representing")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// all the selected fields for a repository and map that to the")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// top-level `repository` query in the Github API.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This means the final query will end up looking something like this:")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// query {")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// repository(owner: r.args.owner, name: r.args.name) {")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// . ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// }")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// }")]),t._v("\n RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromFunction"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ResolveRequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n name "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"repository"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n arguments "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Map"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"owner"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" Value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" Value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromUrl"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GITHUB_API"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("provide"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sttpClient"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("However, when running this we will experience failing requests due to "),s("code",[t._v("401 Unauthorized")]),t._v(". This is because all queries to Github's API requires authorization to be provided. In order to fix this, we need to add authorization to both the introspection query as well as our remote resolver. We also need a config module that can provide us with a Github token based on the value of "),s("code",[t._v("GITHUB_TOKEN")]),t._v(" in our environment.")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Configuration"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("githubToken"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" Configuration "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" fromEnvironment "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n githubToken "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" read"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GITHUB_TOKEN"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" Configuration"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("githubToken"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toLayer\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" read"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Task"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Task"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("effect"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n sys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("env"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("We can now update the introspection query to use our token:")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n config "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ZIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("environment"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Has"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Configuration"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n schemaLoader "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" SchemaLoader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromIntrospection"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n GITHUB_API"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Some"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n List"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Options"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Authorization"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string-interpolation"}},[s("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bearer ')]),s("span",{pre:!0,attrs:{class:"token interpolation"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),s("span",{pre:!0,attrs:{class:"token expression"}},[t._v("config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("get"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("githubToken")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")])]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n")])])]),s("p",[t._v("as well as update our resolver to authorize our request.")]),t._v(" "),s("p",[t._v("In order to do this, we can use "),s("code",[t._v("RemoteResolver[R, E, A, B]")]),t._v(" which lets us compose resolution steps via "),s("code",[t._v(">>>")]),t._v(".")]),t._v(" "),s("p",[t._v("In order to make this code easier, we can extract the mechanics around sending the actual request:")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" apiRequest "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toQuery "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GITHUB_API"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromFunctionM"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" HttpRequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n config "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("<-")]),t._v(" ZIO"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("service"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Configuration"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("yield")]),t._v(" r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Authorization"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-interpolation"}},[s("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bearer ')]),s("span",{pre:!0,attrs:{class:"token interpolation"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),s("span",{pre:!0,attrs:{class:"token expression"}},[t._v("config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("githubToken")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")])]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("execute "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("unwrap\n")])])]),s("p",[t._v("And now we can use our new "),s("code",[t._v("apiRequest")]),t._v(" when resolving our "),s("code",[t._v("Schema[ZEnv, Repository]")]),t._v(":")]),t._v(" "),s("div",{staticClass:"language-scala extra-class"},[s("pre",{pre:!0,attrs:{class:"language-scala"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" githubProfileSchema"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n remoteSchemaResolvers\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("remoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Repository"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n RemoteResolver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("fromFunction"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ResolveRequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Repository"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v("\n r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("field"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("copy"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n name "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"repository"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n arguments "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Map"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"owner"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" Value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" Value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StringValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>>")]),t._v(" apiRequest\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("provide"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sttpClient "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("All that's left to do is to hook up to an HTTP server and configure a Github API token. And now you have an API that can handle queries such as these:")]),t._v(" "),s("div",{staticClass:"language-graphql extra-class"},[s("pre",{pre:!0,attrs:{class:"language-graphql"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("query")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property-query"}},[t._v("GetUser")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ghostdogpr"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("repository")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("id")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("name")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("featuredRepository")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property-query"}},[t._v("pullRequests")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("states")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("OPEN")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("first")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("edges")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("node")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("title")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token object"}},[t._v("author")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token property"}},[t._v("login")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("See the "),s("a",{attrs:{href:"https://github.com/ghostdogpr/caliban/tree/series/2.x/examples/src/main/scala/example/stitching",target:"_blank",rel:"noopener noreferrer"}},[t._v("examples directory"),s("OutboundLink")],1),t._v(" for a full example.")]),t._v(" "),s("h2",{attrs:{id:"things-not-yet-supported"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#things-not-yet-supported"}},[t._v("#")]),t._v(" Things not yet supported")]),t._v(" "),s("ul",[s("li",[t._v("Type renaming.")]),t._v(" "),s("li",[t._v("Type conflict resolution strategies.")])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/41.52247050.js b/docs/assets/js/40.8a7ce965.js similarity index 96% rename from docs/assets/js/41.52247050.js rename to docs/assets/js/40.8a7ce965.js index 8708dd6b71..c34c22693b 100644 --- a/docs/assets/js/41.52247050.js +++ b/docs/assets/js/40.8a7ce965.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[41],{322:function(t,e,a){"use strict";a.r(e);var s=a(14),o=Object(s.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"getting-started"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#getting-started"}},[t._v("#")]),t._v(" Getting Started")]),t._v(" "),e("p",[t._v("Caliban comes with a module called "),e("code",[t._v("caliban-tools")]),t._v(" that exposes some useful features:")]),t._v(" "),e("ul",[e("li",[t._v("all the code generation features from "),e("code",[t._v("caliban-codegen-sbt")]),t._v(", so that you can use them without sbt: see "),e("code",[t._v("caliban.tools.Codegen")]),t._v(".")]),t._v(" "),e("li",[t._v("a client for GraphQL introspection: see "),e("code",[t._v("caliban.tools.IntrospectionClient")]),t._v(".")]),t._v(" "),e("li",[t._v("utilities for "),e("RouterLink",{attrs:{to:"/docs/stitching.html"}},[t._v("stitching GraphQL schemas")]),t._v(".")],1),t._v(" "),e("li",[t._v("a way to "),e("RouterLink",{attrs:{to:"/docs/schema-comparison.html"}},[t._v("compare GraphQL schemas")]),t._v(", whether they come from Caliban or a remote server.")],1)]),t._v(" "),e("h2",{attrs:{id:"dependency"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#dependency"}},[t._v("#")]),t._v(" Dependency")]),t._v(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-tools"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v("\n")])])])])}),[],!1,null,null,null);e.default=o.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[40],{321:function(t,e,a){"use strict";a.r(e);var s=a(14),o=Object(s.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"getting-started"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#getting-started"}},[t._v("#")]),t._v(" Getting Started")]),t._v(" "),e("p",[t._v("Caliban comes with a module called "),e("code",[t._v("caliban-tools")]),t._v(" that exposes some useful features:")]),t._v(" "),e("ul",[e("li",[t._v("all the code generation features from "),e("code",[t._v("caliban-codegen-sbt")]),t._v(", so that you can use them without sbt: see "),e("code",[t._v("caliban.tools.Codegen")]),t._v(".")]),t._v(" "),e("li",[t._v("a client for GraphQL introspection: see "),e("code",[t._v("caliban.tools.IntrospectionClient")]),t._v(".")]),t._v(" "),e("li",[t._v("utilities for "),e("RouterLink",{attrs:{to:"/docs/stitching.html"}},[t._v("stitching GraphQL schemas")]),t._v(".")],1),t._v(" "),e("li",[t._v("a way to "),e("RouterLink",{attrs:{to:"/docs/schema-comparison.html"}},[t._v("compare GraphQL schemas")]),t._v(", whether they come from Caliban or a remote server.")],1)]),t._v(" "),e("h2",{attrs:{id:"dependency"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#dependency"}},[t._v("#")]),t._v(" Dependency")]),t._v(" "),e("div",{staticClass:"language-scala extra-class"},[e("pre",{pre:!0,attrs:{class:"language-scala"}},[e("code",[e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"com.github.ghostdogpr"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"caliban-tools"')]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.6.0"')]),t._v("\n")])])])])}),[],!1,null,null,null);e.default=o.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/43.8339688b.js b/docs/assets/js/41.ab98ab0d.js similarity index 94% rename from docs/assets/js/43.8339688b.js rename to docs/assets/js/41.ab98ab0d.js index 974f5ba8e0..1465098db4 100644 --- a/docs/assets/js/43.8339688b.js +++ b/docs/assets/js/41.ab98ab0d.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[43],{324:function(t,a,e){"use strict";e.r(a);var s=e(14),n=Object(s.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"faq"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#faq"}},[t._v("#")]),t._v(" FAQ")]),t._v(" "),a("h3",{attrs:{id:"i-don-t-know-where-to-start-😥"}},[a("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(" "),a("p",[t._v("No worries! Head to the "),a("a",{attrs:{href:"https://ghostdogpr.github.io/caliban/resources/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Resources"),a("OutboundLink")],1),t._v(" page to find a few introductory videos and blog posts. Once you're ready for more details, check the "),a("a",{attrs:{href:"https://ghostdogpr.github.io/caliban/docs/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Documentation"),a("OutboundLink")],1),t._v(". If you prefer looking at some code first, check "),a("a",{attrs:{href:"https://ghostdogpr.github.io/caliban/docs/examples.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("this list of examples"),a("OutboundLink")],1),t._v(".")]),t._v(" "),a("p",[t._v("If you're still lost, just come to the "),a("a",{attrs:{href:"https://discord.gg/EYpumuv",target:"_blank",rel:"noopener noreferrer"}},[t._v("Discord channel"),a("OutboundLink")],1),t._v("!")]),t._v(" "),a("h3",{attrs:{id:"i-m-getting-a-compilation-error-saying-a-schema-is-missing-but-i-don-t-know-which-one"}},[a("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 "),a("code",[t._v("Schema")]),t._v(" is missing, but I don't know which one.")]),t._v(" "),a("p",[t._v("Call directly "),a("code",[t._v("Schema.gen[YourType]")]),t._v(" or just "),a("code",[t._v("gen[YourType]")]),t._v(" if you extend "),a("code",[t._v("GenericSchema")]),t._v(". The error should be more detailed.\nIt is also recommended to use semi-auto derivation instead of auto derivation, as it will tell you more clearly which type is missing a schema.")]),t._v(" "),a("h3",{attrs:{id:"i-want-to-use-caliban-but-i-use-cats-effect-monix-instead-of-zio"}},[a("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(" "),a("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 '),a("a",{attrs:{href:"https://ghostdogpr.github.io/caliban/docs/interop.html#cats-effect",target:"_blank",rel:"noopener noreferrer"}},[t._v("interop docs"),a("OutboundLink")],1),t._v(" for more details.")]),t._v(" "),a("h3",{attrs:{id:"my-query-fails-with-an-effect-failure-error-how-can-i-get-more-details"}},[a("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(" "),a("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(" "),a("ol",[a("li",[t._v("If you fail with a "),a("code",[t._v("CalibanError.ExecutionError")]),t._v(", it won't be wrapped by Caliban so the original message will be displayed")]),t._v(" "),a("li",[t._v("Using the wrapper "),a("code",[t._v("@@ printErrors")]),t._v(" will print the full error to the console")]),t._v(" "),a("li",[t._v("Using "),a("code",[t._v("mapError")]),t._v(" on your interpreter lets you unwrap the "),a("code",[t._v("CalibanError")]),t._v(" and return your inner exception instead")])]),t._v(" "),a("h3",{attrs:{id:"i-have-more-than-22-fields-in-my-query-i-can-t-create-a-case-class-for-it"}},[a("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(" "),a("p",[t._v("Instead of one huge case class with all your fields, you can create smaller case classes and combine "),a("code",[t._v("GraphQL")]),t._v(" objects using "),a("code",[t._v("|+|")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api2 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\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(" api1 "),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(" api2\n")])])]),a("h3",{attrs:{id:"how-to-deal-with-authentication-authorization"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#how-to-deal-with-authentication-authorization"}},[t._v("#")]),t._v(" How to deal with authentication/authorization?")]),t._v(" "),a("p",[t._v("This is typically handled with the help of ZIO environment. You can make your field require an "),a("code",[t._v("Auth")]),t._v(" service by returning a "),a("code",[t._v("ZIO[Auth, E, A]")]),t._v(". Then, in your resolver, access the "),a("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 "),a("a",{attrs:{href:"https://github.com/search?q=repo%3Aghostdogpr%2Fcaliban+AuthExampleApp+language%3AScala&type=code&l=Scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1),t._v(" for a list of examples with different adapters.")]),t._v(" "),a("h3",{attrs:{id:"i-have-2-case-classes-with-the-same-name-different-packages-how-to-avoid-conflicts"}},[a("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(" "),a("p",[t._v("You can use the annotation "),a("code",[t._v("@GQLName")]),t._v(" to give another name to any type or field.")]),t._v(" "),a("h3",{attrs:{id:"the-auto-generated-schema-shows-a-field-is-nullable-but-i-want-it-non-nullable-instead"}},[a("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(" "),a("p",[t._v("A GraphQL field is marked as nullable if the Scala field returns an "),a("code",[t._v("Option")]),t._v(" or an effect that can fail. Change your effect to return "),a("code",[t._v("UIO")]),t._v(" if you want the field to be non-nullable, and use "),a("code",[t._v("orDie")]),t._v(" if you want to fail the whole query in case of error instead of returning null.")]),t._v(" "),a("h3",{attrs:{id:"can-i-use-a-union-as-input"}},[a("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(" "),a("p",[t._v("Unfortunately, it is not supported by the GraphQL spec. See "),a("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"),a("OutboundLink")],1),t._v(" for discussions. An alternative can be to define your own custom scalar.")]),t._v(" "),a("h3",{attrs:{id:"how-to-deal-with-recursive-types"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#how-to-deal-with-recursive-types"}},[t._v("#")]),t._v(" How to deal with recursive types?")]),t._v(" "),a("p",[t._v("Recursive types can be a little tricky. This is not a silver bullet but usually the trick is to add an "),a("code",[t._v("implicit lazy val")]),t._v(" instance of "),a("code",[t._v("Schema")]),t._v(" for the type that is recursive. See "),a("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"),a("OutboundLink")],1),t._v(" for an example.")]),t._v(" "),a("h3",{attrs:{id:"i-m-getting-a-method-too-large-compiler-error"}},[a("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(" "),a("p",[t._v("When you create a GraphQL API and use auto schema derivation, Caliban generates a schema for every type, everywhere it's used. If you have a lot of types, the generated code might be too large. The workaround is to use semi-auto derivation instead and define a "),a("code",[t._v("Schema")]),t._v(" for each of your case classes and sealed traits:")]),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(" schemaMyType"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])]),a("p",[t._v("That way, the schema for this type will be extracted to a single method and defined only once.")]),t._v(" "),a("h3",{attrs:{id:"how-can-i-define-a-schema-for-a-java-enum"}},[a("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 "),a("code",[t._v("Schema")]),t._v(" for a Java enum?")]),t._v(" "),a("p",[t._v("Here's an example for Java "),a("code",[t._v("DayOfWeek")]),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(" dayOfWeekSchema "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" DayOfWeek"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" toType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("isInput"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Boolean")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" __Type "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Types"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("makeEnum"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"DayOfWeek"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n DayOfWeek"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("values"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toList"),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("v "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" __EnumValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),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(" None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n None\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" resolve"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" DayOfWeek"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Step"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" PureStep"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h3",{attrs:{id:"i-don-t-want-to-use-throwable-as-my-error-type"}},[a("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 "),a("code",[t._v("Throwable")]),t._v(" as my error type")]),t._v(" "),a("p",[t._v("Caliban provides "),a("code",[t._v("Schema")]),t._v(" instances for "),a("code",[t._v("ZIO")]),t._v(", "),a("code",[t._v("ZQuery")]),t._v(" and "),a("code",[t._v("ZStream")]),t._v(" but with the condition that the error type is a "),a("code",[t._v("Throwable")]),t._v(".\nThat is because the error is eventually wrapped inside Caliban "),a("code",[t._v("ExecutionError")]),t._v(" and we need to know what it is.\nHowever, you can easily define a custom "),a("code",[t._v("Schema")]),t._v(" without this constraint, as long as you provide a function from your error type to "),a("code",[t._v("ExecutionError")]),t._v(".")]),t._v(" "),a("p",[t._v("For example, if your error type is "),a("code",[t._v("Int")]),t._v(", you can use "),a("code",[t._v("Schema.customErrorEffectSchema")]),t._v(" as follows:")]),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("def")]),t._v(" customEffectSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" s"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("customErrorEffectSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("code"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Error code ')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("code")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("With this implicit in scope, Caliban will know how to handle any "),a("code",[t._v("IO[Int, A]")]),t._v(" effects.\nCaliban will automatically fill the error path and the error location inside "),a("code",[t._v("ExecutionError")]),t._v(" if an error happens during the query execution.")]),t._v(" "),a("h3",{attrs:{id:"my-interface-is-missing-from-the-schema"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#my-interface-is-missing-from-the-schema"}},[t._v("#")]),t._v(" My interface is missing from the schema")]),t._v(" "),a("p",[t._v("If you have an interface that is not directly returned by any field, it will be missing from the schema. This is a constraint from the way the typeclass derivation works. A workaround is to use "),a("code",[t._v("withAdditionalTypes")]),t._v(" on your "),a("code",[t._v("GraphQL")]),t._v(" object to explicitly add the interface. See the following example:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Annotations"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLInterface")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Interface\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(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Interface\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(" B"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Interface\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" b"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" B"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" interfaceType "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Interface"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toType_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"a"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" B"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"b"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("withAdditionalTypes"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("interfaceType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[41],{322:function(t,a,e){"use strict";e.r(a);var s=e(14),n=Object(s.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"faq"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#faq"}},[t._v("#")]),t._v(" FAQ")]),t._v(" "),a("h3",{attrs:{id:"i-don-t-know-where-to-start-😥"}},[a("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(" "),a("p",[t._v("No worries! Head to the "),a("a",{attrs:{href:"https://ghostdogpr.github.io/caliban/resources/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Resources"),a("OutboundLink")],1),t._v(" page to find a few introductory videos and blog posts. Once you're ready for more details, check the "),a("a",{attrs:{href:"https://ghostdogpr.github.io/caliban/docs/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Documentation"),a("OutboundLink")],1),t._v(". If you prefer looking at some code first, check "),a("a",{attrs:{href:"https://ghostdogpr.github.io/caliban/docs/examples.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("this list of examples"),a("OutboundLink")],1),t._v(".")]),t._v(" "),a("p",[t._v("If you're still lost, just come to the "),a("a",{attrs:{href:"https://discord.gg/EYpumuv",target:"_blank",rel:"noopener noreferrer"}},[t._v("Discord channel"),a("OutboundLink")],1),t._v("!")]),t._v(" "),a("h3",{attrs:{id:"i-m-getting-a-compilation-error-saying-a-schema-is-missing-but-i-don-t-know-which-one"}},[a("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 "),a("code",[t._v("Schema")]),t._v(" is missing, but I don't know which one.")]),t._v(" "),a("p",[t._v("Call directly "),a("code",[t._v("Schema.gen[YourType]")]),t._v(" or just "),a("code",[t._v("gen[YourType]")]),t._v(" if you extend "),a("code",[t._v("GenericSchema")]),t._v(". The error should be more detailed.\nIt is also recommended to use semi-auto derivation instead of auto derivation, as it will tell you more clearly which type is missing a schema.")]),t._v(" "),a("h3",{attrs:{id:"i-want-to-use-caliban-but-i-use-cats-effect-monix-instead-of-zio"}},[a("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(" "),a("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 '),a("a",{attrs:{href:"https://ghostdogpr.github.io/caliban/docs/interop.html#cats-effect",target:"_blank",rel:"noopener noreferrer"}},[t._v("interop docs"),a("OutboundLink")],1),t._v(" for more details.")]),t._v(" "),a("h3",{attrs:{id:"my-query-fails-with-an-effect-failure-error-how-can-i-get-more-details"}},[a("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(" "),a("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(" "),a("ol",[a("li",[t._v("If you fail with a "),a("code",[t._v("CalibanError.ExecutionError")]),t._v(", it won't be wrapped by Caliban so the original message will be displayed")]),t._v(" "),a("li",[t._v("Using the wrapper "),a("code",[t._v("@@ printErrors")]),t._v(" will print the full error to the console")]),t._v(" "),a("li",[t._v("Using "),a("code",[t._v("mapError")]),t._v(" on your interpreter lets you unwrap the "),a("code",[t._v("CalibanError")]),t._v(" and return your inner exception instead")])]),t._v(" "),a("h3",{attrs:{id:"i-have-more-than-22-fields-in-my-query-i-can-t-create-a-case-class-for-it"}},[a("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(" "),a("p",[t._v("Instead of one huge case class with all your fields, you can create smaller case classes and combine "),a("code",[t._v("GraphQL")]),t._v(" objects using "),a("code",[t._v("|+|")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api2 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\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(" api1 "),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(" api2\n")])])]),a("h3",{attrs:{id:"how-to-deal-with-authentication-authorization"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#how-to-deal-with-authentication-authorization"}},[t._v("#")]),t._v(" How to deal with authentication/authorization?")]),t._v(" "),a("p",[t._v("This is typically handled with the help of ZIO environment. You can make your field require an "),a("code",[t._v("Auth")]),t._v(" service by returning a "),a("code",[t._v("ZIO[Auth, E, A]")]),t._v(". Then, in your resolver, access the "),a("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 "),a("a",{attrs:{href:"https://github.com/search?q=repo%3Aghostdogpr%2Fcaliban+AuthExampleApp+language%3AScala&type=code&l=Scala",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1),t._v(" for a list of examples with different adapters.")]),t._v(" "),a("h3",{attrs:{id:"i-have-2-case-classes-with-the-same-name-different-packages-how-to-avoid-conflicts"}},[a("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(" "),a("p",[t._v("You can use the annotation "),a("code",[t._v("@GQLName")]),t._v(" to give another name to any type or field.")]),t._v(" "),a("h3",{attrs:{id:"the-auto-generated-schema-shows-a-field-is-nullable-but-i-want-it-non-nullable-instead"}},[a("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(" "),a("p",[t._v("A GraphQL field is marked as nullable if the Scala field returns an "),a("code",[t._v("Option")]),t._v(" or an effect that can fail. Change your effect to return "),a("code",[t._v("UIO")]),t._v(" if you want the field to be non-nullable, and use "),a("code",[t._v("orDie")]),t._v(" if you want to fail the whole query in case of error instead of returning null.")]),t._v(" "),a("h3",{attrs:{id:"can-i-use-a-union-as-input"}},[a("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(" "),a("p",[t._v("Unfortunately, it is not supported by the GraphQL spec. See "),a("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"),a("OutboundLink")],1),t._v(" for discussions. An alternative can be to define your own custom scalar.")]),t._v(" "),a("h3",{attrs:{id:"how-to-deal-with-recursive-types"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#how-to-deal-with-recursive-types"}},[t._v("#")]),t._v(" How to deal with recursive types?")]),t._v(" "),a("p",[t._v("Recursive types can be a little tricky. This is not a silver bullet but usually the trick is to add an "),a("code",[t._v("implicit lazy val")]),t._v(" instance of "),a("code",[t._v("Schema")]),t._v(" for the type that is recursive. See "),a("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"),a("OutboundLink")],1),t._v(" for an example.")]),t._v(" "),a("h3",{attrs:{id:"i-m-getting-a-method-too-large-compiler-error"}},[a("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(" "),a("p",[t._v("When you create a GraphQL API and use auto schema derivation, Caliban generates a schema for every type, everywhere it's used. If you have a lot of types, the generated code might be too large. The workaround is to use semi-auto derivation instead and define a "),a("code",[t._v("Schema")]),t._v(" for each of your case classes and sealed traits:")]),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(" schemaMyType"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" MyType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen\n")])])]),a("p",[t._v("That way, the schema for this type will be extracted to a single method and defined only once.")]),t._v(" "),a("h3",{attrs:{id:"how-can-i-define-a-schema-for-a-java-enum"}},[a("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 "),a("code",[t._v("Schema")]),t._v(" for a Java enum?")]),t._v(" "),a("p",[t._v("Here's an example for Java "),a("code",[t._v("DayOfWeek")]),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(" dayOfWeekSchema "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" DayOfWeek"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" toType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("isInput"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Boolean")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" __Type "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Types"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("makeEnum"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"DayOfWeek"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n DayOfWeek"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("values"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toList"),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("v "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" __EnumValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),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(" None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" None"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n None\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" resolve"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" DayOfWeek"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Step"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" PureStep"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("StringValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h3",{attrs:{id:"i-don-t-want-to-use-throwable-as-my-error-type"}},[a("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 "),a("code",[t._v("Throwable")]),t._v(" as my error type")]),t._v(" "),a("p",[t._v("Caliban provides "),a("code",[t._v("Schema")]),t._v(" instances for "),a("code",[t._v("ZIO")]),t._v(", "),a("code",[t._v("ZQuery")]),t._v(" and "),a("code",[t._v("ZStream")]),t._v(" but with the condition that the error type is a "),a("code",[t._v("Throwable")]),t._v(".\nThat is because the error is eventually wrapped inside Caliban "),a("code",[t._v("ExecutionError")]),t._v(" and we need to know what it is.\nHowever, you can easily define a custom "),a("code",[t._v("Schema")]),t._v(" without this constraint, as long as you provide a function from your error type to "),a("code",[t._v("ExecutionError")]),t._v(".")]),t._v(" "),a("p",[t._v("For example, if your error type is "),a("code",[t._v("Int")]),t._v(", you can use "),a("code",[t._v("Schema.customErrorEffectSchema")]),t._v(" as follows:")]),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("def")]),t._v(" customEffectSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("implicit")]),t._v(" s"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("customErrorEffectSchema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("code"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("=>")]),t._v(" ExecutionError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string-interpolation"}},[a("span",{pre:!0,attrs:{class:"token id function"}},[t._v("s")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Error code ')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("code")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("With this implicit in scope, Caliban will know how to handle any "),a("code",[t._v("IO[Int, A]")]),t._v(" effects.\nCaliban will automatically fill the error path and the error location inside "),a("code",[t._v("ExecutionError")]),t._v(" if an error happens during the query execution.")]),t._v(" "),a("h3",{attrs:{id:"my-interface-is-missing-from-the-schema"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#my-interface-is-missing-from-the-schema"}},[t._v("#")]),t._v(" My interface is missing from the schema")]),t._v(" "),a("p",[t._v("If you have an interface that is not directly returned by any field, it will be missing from the schema. This is a constraint from the way the typeclass derivation works. A workaround is to use "),a("code",[t._v("withAdditionalTypes")]),t._v(" on your "),a("code",[t._v("GraphQL")]),t._v(" object to explicitly add the interface. See the following example:")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Annotations"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("auto"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_\n\n"),a("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@GQLInterface")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sealed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" Interface\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(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Interface\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(" B"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" Interface\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" b"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" B"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" interfaceType "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Schema"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gen"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Interface"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("toType_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" api "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" graphQL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("RootResolver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Query"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"a"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" B"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"b"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("withAdditionalTypes"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("List"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("interfaceType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h3",{attrs:{id:"can-i-check-that-a-graphql-query-is-valid-at-compile-time"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#can-i-check-that-a-graphql-query-is-valid-at-compile-time"}},[t._v("#")]),t._v(" Can I check that a GraphQL query is valid at compile-time?")]),t._v(" "),a("p",[t._v("Caliban provides a little macro called "),a("code",[t._v("gqldoc")]),t._v(" that can check at "),a("strong",[t._v("compile-time")]),t._v(" that a GraphQL query (a "),a("em",[t._v("document")]),t._v(" to be exact) has valid syntax.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Macros"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gqldoc\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" query "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" gqldoc"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token triple-quoted-string string"}},[t._v('"""\n query test {\n amos: character(name: "Amos Burton") {\n name\n }\n }"""')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/42.99036692.js b/docs/assets/js/42.99036692.js deleted file mode 100644 index 4c1a8fcb61..0000000000 --- a/docs/assets/js/42.99036692.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[42],{323:function(t,a,s){"use strict";s.r(a);var e=s(14),n=Object(e.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"validation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#validation"}},[t._v("#")]),t._v(" Validation")]),t._v(" "),a("p",[t._v("Caliban provides a little macro called "),a("code",[t._v("gqldoc")]),t._v(" that can check at "),a("strong",[t._v("compile-time")]),t._v(" that a GraphQL query (a "),a("em",[t._v("document")]),t._v(" to be exact) has valid syntax.")]),t._v(" "),a("div",{staticClass:"language-scala mdoc:silent extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("caliban"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),t._v("Macros"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gqldoc\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" query "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" gqldoc"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token triple-quoted-string string"}},[t._v('"""\n query test {\n amos: character(name: "Amos Burton") {\n name\n }\n }"""')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("At "),a("strong",[t._v("runtime")]),t._v(", it is possible to validate a query against your schema by calling the method "),a("code",[t._v("check")]),t._v(" on your API.")]),t._v(" "),a("div",{staticClass:"language-scala extra-class"},[a("pre",{pre:!0,attrs:{class:"language-scala"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("def")]),t._v(" check"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("query"),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(" IO"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("CalibanError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("Unit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n")])])]),a("p",[t._v("It is also possible to skip validation when executing a query by passing "),a("code",[t._v("Configurator.setSkipValidation(true)")]),t._v(" to the "),a("code",[t._v("configure")]),t._v(" function of your http/ws interpreter. This will slightly improve performance.")])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/44.e00ae25b.js b/docs/assets/js/42.b28d8bbd.js similarity index 98% rename from docs/assets/js/44.e00ae25b.js rename to docs/assets/js/42.b28d8bbd.js index d7888b41aa..0999bad61f 100644 --- a/docs/assets/js/44.e00ae25b.js +++ b/docs/assets/js/42.b28d8bbd.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[44],{325:function(a,e,r){"use strict";r.r(e);var t=r(14),n=Object(t.a)({},(function(){var a=this,e=a._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[e("h1",{attrs:{id:"resources"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#resources"}},[a._v("#")]),a._v(" Resources")]),a._v(" "),e("h2",{attrs:{id:"talks"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#talks"}},[a._v("#")]),a._v(" Talks")]),a._v(" "),e("ul",[e("li",[e("a",{attrs:{href:"https://www.youtube.com/watch?v=pYfWq4GmObY",target:"_blank",rel:"noopener noreferrer"}},[a._v("Cost-effective and easy to maintain GraphQL integration tests"),e("OutboundLink")],1),a._v(" by Jules Ivanic at "),e("a",{attrs:{href:"https://www.functionalscala.com/",target:"_blank",rel:"noopener noreferrer"}},[a._v("Functional Scala"),e("OutboundLink")],1),a._v(" in December 2022")]),a._v(" "),e("li",[e("a",{attrs:{href:"https://youtu.be/mzqsXklbmfM",target:"_blank",rel:"noopener noreferrer"}},[a._v("Zymposium episode on Caliban"),e("OutboundLink")],1),a._v(" with Pierre Ricadat, Kit Langton and Adam Fraser in June 2021")]),a._v(" "),e("li",[e("a",{attrs:{href:"https://www.youtube.com/watch?v=lgxUKsOH65k",target:"_blank",rel:"noopener noreferrer"}},[a._v("A Tour of Caliban"),e("OutboundLink")],1),a._v(" by Pierre Ricadat at "),e("a",{attrs:{href:"https://www.meetup.com/SF-Scala/",target:"_blank",rel:"noopener noreferrer"}},[a._v("SF Scala"),e("OutboundLink")],1),a._v(" in April 2020")]),a._v(" "),e("li",[e("a",{attrs:{href:"https://www.youtube.com/watch?v=OC8PbviYUlQ",target:"_blank",rel:"noopener noreferrer"}},[a._v("Caliban: Designing a Functional GraphQL Library"),e("OutboundLink")],1),a._v(" by Pierre Ricadat at "),e("a",{attrs:{href:"https://www.functionalscala.com/",target:"_blank",rel:"noopener noreferrer"}},[a._v("Functional Scala"),e("OutboundLink")],1),a._v(" in December 2019 (slides available "),e("a",{attrs:{href:"https://www.slideshare.net/PierreRicadat/designing-a-functional-graphql-library-204680947",target:"_blank",rel:"noopener noreferrer"}},[a._v("here"),e("OutboundLink")],1),a._v(")")])]),a._v(" "),e("h2",{attrs:{id:"blog-articles"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#blog-articles"}},[a._v("#")]),a._v(" Blog Articles")]),a._v(" "),e("ul",[e("li",[e("a",{attrs:{href:"https://blog.pierre-ricadat.com/series/graphql-in-scala",target:"_blank",rel:"noopener noreferrer"}},[a._v("GraphQL in Scala"),e("OutboundLink")],1),a._v(" a blog series by Pierre Ricadat (December 2023)")]),a._v(" "),e("li",[e("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"),e("OutboundLink")],1),a._v(" by Pierre Ricadat (February 2020)")]),a._v(" "),e("li",[e("strong",[e("em",[a._v("GraphQL in Scala with Caliban")])]),a._v(" by Pierre Ricadat (February 2020)\n"),e("ul",[e("li",[e("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"),e("OutboundLink")],1)]),a._v(" "),e("li",[e("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"),e("OutboundLink")],1)]),a._v(" "),e("li",[e("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"),e("OutboundLink")],1)])])]),a._v(" "),e("li",[e("a",{attrs:{href:"http://fokot.github.io/post/caliban-auth.html",target:"_blank",rel:"noopener noreferrer"}},[a._v("Authentication in Caliban"),e("OutboundLink")],1),a._v(" by František Kocun (December 2019)")])]),a._v(" "),e("h2",{attrs:{id:"related-projects"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#related-projects"}},[a._v("#")]),a._v(" Related Projects")]),a._v(" "),e("ul",[e("li",[e("a",{attrs:{href:"https://zio.github.io/caliban-deriving/",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-deriving"),e("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(" "),e("li",[e("a",{attrs:{href:"https://github.com/niqdev/caliban-extras",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-extras"),e("OutboundLink")],1),a._v(": a project bringing some goodies to caliban, including "),e("a",{attrs:{href:"https://github.com/niqdev/caliban-extras#caliban-refined",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-refined"),e("OutboundLink")],1),a._v(", a module to automatically derive schemas for "),e("a",{attrs:{href:"https://github.com/fthomas/refined",target:"_blank",rel:"noopener noreferrer"}},[a._v("refined"),e("OutboundLink")],1),a._v(" types.")]),a._v(" "),e("li",[e("a",{attrs:{href:"https://github.com/ScalaConsultants/zio-akka-quickstart.g8",target:"_blank",rel:"noopener noreferrer"}},[a._v("zio-akka-quickstart"),e("OutboundLink")],1),a._v(": a Giter8 template for a basic Scala application built using ZIO, Akka HTTP, Slick and Caliban!")]),a._v(" "),e("li",[e("a",{attrs:{href:"https://github.com/fokot/caliban-talk",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-talk"),e("OutboundLink")],1),a._v(": example project using ZIO, http4s, doobie/quill, caliban-client, testcontainers and Caliban")]),a._v(" "),e("li",[e("a",{attrs:{href:"https://github.com/swachter/caliban-test",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-test"),e("OutboundLink")],1),a._v(": example project using ZIO, Caliban, and jOOQ for accessing a relation database")]),a._v(" "),e("li",[e("a",{attrs:{href:"https://github.com/CarlosLaraFP/Cases",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-zio-http-cats"),e("OutboundLink")],1),a._v(": real technical interview project using ZIO, Caliban, Doobie, Cats core, and domain error modeling (passed + job offer)")])])])}),[],!1,null,null,null);e.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[42],{323:function(a,e,r){"use strict";r.r(e);var t=r(14),n=Object(t.a)({},(function(){var a=this,e=a._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[e("h1",{attrs:{id:"resources"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#resources"}},[a._v("#")]),a._v(" Resources")]),a._v(" "),e("h2",{attrs:{id:"talks"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#talks"}},[a._v("#")]),a._v(" Talks")]),a._v(" "),e("ul",[e("li",[e("a",{attrs:{href:"https://www.youtube.com/watch?v=pYfWq4GmObY",target:"_blank",rel:"noopener noreferrer"}},[a._v("Cost-effective and easy to maintain GraphQL integration tests"),e("OutboundLink")],1),a._v(" by Jules Ivanic at "),e("a",{attrs:{href:"https://www.functionalscala.com/",target:"_blank",rel:"noopener noreferrer"}},[a._v("Functional Scala"),e("OutboundLink")],1),a._v(" in December 2022")]),a._v(" "),e("li",[e("a",{attrs:{href:"https://youtu.be/mzqsXklbmfM",target:"_blank",rel:"noopener noreferrer"}},[a._v("Zymposium episode on Caliban"),e("OutboundLink")],1),a._v(" with Pierre Ricadat, Kit Langton and Adam Fraser in June 2021")]),a._v(" "),e("li",[e("a",{attrs:{href:"https://www.youtube.com/watch?v=lgxUKsOH65k",target:"_blank",rel:"noopener noreferrer"}},[a._v("A Tour of Caliban"),e("OutboundLink")],1),a._v(" by Pierre Ricadat at "),e("a",{attrs:{href:"https://www.meetup.com/SF-Scala/",target:"_blank",rel:"noopener noreferrer"}},[a._v("SF Scala"),e("OutboundLink")],1),a._v(" in April 2020")]),a._v(" "),e("li",[e("a",{attrs:{href:"https://www.youtube.com/watch?v=OC8PbviYUlQ",target:"_blank",rel:"noopener noreferrer"}},[a._v("Caliban: Designing a Functional GraphQL Library"),e("OutboundLink")],1),a._v(" by Pierre Ricadat at "),e("a",{attrs:{href:"https://www.functionalscala.com/",target:"_blank",rel:"noopener noreferrer"}},[a._v("Functional Scala"),e("OutboundLink")],1),a._v(" in December 2019 (slides available "),e("a",{attrs:{href:"https://www.slideshare.net/PierreRicadat/designing-a-functional-graphql-library-204680947",target:"_blank",rel:"noopener noreferrer"}},[a._v("here"),e("OutboundLink")],1),a._v(")")])]),a._v(" "),e("h2",{attrs:{id:"blog-articles"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#blog-articles"}},[a._v("#")]),a._v(" Blog Articles")]),a._v(" "),e("ul",[e("li",[e("a",{attrs:{href:"https://blog.pierre-ricadat.com/series/graphql-in-scala",target:"_blank",rel:"noopener noreferrer"}},[a._v("GraphQL in Scala"),e("OutboundLink")],1),a._v(" a blog series by Pierre Ricadat (December 2023)")]),a._v(" "),e("li",[e("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"),e("OutboundLink")],1),a._v(" by Pierre Ricadat (February 2020)")]),a._v(" "),e("li",[e("strong",[e("em",[a._v("GraphQL in Scala with Caliban")])]),a._v(" by Pierre Ricadat (February 2020)\n"),e("ul",[e("li",[e("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"),e("OutboundLink")],1)]),a._v(" "),e("li",[e("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"),e("OutboundLink")],1)]),a._v(" "),e("li",[e("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"),e("OutboundLink")],1)])])]),a._v(" "),e("li",[e("a",{attrs:{href:"http://fokot.github.io/post/caliban-auth.html",target:"_blank",rel:"noopener noreferrer"}},[a._v("Authentication in Caliban"),e("OutboundLink")],1),a._v(" by František Kocun (December 2019)")])]),a._v(" "),e("h2",{attrs:{id:"related-projects"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#related-projects"}},[a._v("#")]),a._v(" Related Projects")]),a._v(" "),e("ul",[e("li",[e("a",{attrs:{href:"https://zio.github.io/caliban-deriving/",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-deriving"),e("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(" "),e("li",[e("a",{attrs:{href:"https://github.com/niqdev/caliban-extras",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-extras"),e("OutboundLink")],1),a._v(": a project bringing some goodies to caliban, including "),e("a",{attrs:{href:"https://github.com/niqdev/caliban-extras#caliban-refined",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-refined"),e("OutboundLink")],1),a._v(", a module to automatically derive schemas for "),e("a",{attrs:{href:"https://github.com/fthomas/refined",target:"_blank",rel:"noopener noreferrer"}},[a._v("refined"),e("OutboundLink")],1),a._v(" types.")]),a._v(" "),e("li",[e("a",{attrs:{href:"https://github.com/ScalaConsultants/zio-akka-quickstart.g8",target:"_blank",rel:"noopener noreferrer"}},[a._v("zio-akka-quickstart"),e("OutboundLink")],1),a._v(": a Giter8 template for a basic Scala application built using ZIO, Akka HTTP, Slick and Caliban!")]),a._v(" "),e("li",[e("a",{attrs:{href:"https://github.com/fokot/caliban-talk",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-talk"),e("OutboundLink")],1),a._v(": example project using ZIO, http4s, doobie/quill, caliban-client, testcontainers and Caliban")]),a._v(" "),e("li",[e("a",{attrs:{href:"https://github.com/swachter/caliban-test",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-test"),e("OutboundLink")],1),a._v(": example project using ZIO, Caliban, and jOOQ for accessing a relation database")]),a._v(" "),e("li",[e("a",{attrs:{href:"https://github.com/CarlosLaraFP/Cases",target:"_blank",rel:"noopener noreferrer"}},[a._v("caliban-zio-http-cats"),e("OutboundLink")],1),a._v(": real technical interview project using ZIO, Caliban, Doobie, Cats core, and domain error modeling (passed + job offer)")])])])}),[],!1,null,null,null);e.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/app.8293a53f.js b/docs/assets/js/app.cd64229a.js similarity index 82% rename from docs/assets/js/app.8293a53f.js rename to docs/assets/js/app.cd64229a.js index b91ce5205d..6993bea52b 100644 --- a/docs/assets/js/app.8293a53f.js +++ b/docs/assets/js/app.cd64229a.js @@ -1,4 +1,4 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[0],[]]);!function(t){function e(e){for(var r,a,s=e[0],c=e[1],u=e[2],f=0,p=[];f
'};function o(t,e,n){return tn?n:t}function i(t){return 100*(-1+t)}n.configure=function(t){var e,n;for(e in t)void 0!==(n=t[e])&&t.hasOwnProperty(e)&&(r[e]=n);return this},n.status=null,n.set=function(t){var e=n.isStarted();t=o(t,r.minimum,1),n.status=1===t?null:t;var c=n.render(!e),u=c.querySelector(r.barSelector),l=r.speed,f=r.easing;return c.offsetWidth,a((function(e){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),s(u,function(t,e,n){var o;return(o="translate3d"===r.positionUsing?{transform:"translate3d("+i(t)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+i(t)+"%,0)"}:{"margin-left":i(t)+"%"}).transition="all "+e+"ms "+n,o}(t,l,f)),1===t?(s(c,{transition:"none",opacity:1}),c.offsetWidth,setTimeout((function(){s(c,{transition:"all "+l+"ms linear",opacity:0}),setTimeout((function(){n.remove(),e()}),l)}),l)):setTimeout(e,l)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var t=function(){setTimeout((function(){n.status&&(n.trickle(),t())}),r.trickleSpeed)};return r.trickle&&t(),this},n.done=function(t){return t||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(t){var e=n.status;return e?("number"!=typeof t&&(t=(1-e)*o(Math.random()*e,.1,.95)),e=o(e+t,0,.994),n.set(e)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},t=0,e=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===e&&n.start(),t++,e++,r.always((function(){0==--e?(t=0,n.done()):n.set((t-e)/t)})),this):this},n.render=function(t){if(n.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var e=document.createElement("div");e.id="nprogress",e.innerHTML=r.template;var o,a=e.querySelector(r.barSelector),c=t?"-100":i(n.status||0),l=document.querySelector(r.parent);return s(a,{transition:"all 0 linear",transform:"translate3d("+c+"%,0,0)"}),r.showSpinner||(o=e.querySelector(r.spinnerSelector))&&p(o),l!=document.body&&u(l,"nprogress-custom-parent"),l.appendChild(e),e},n.remove=function(){l(document.documentElement,"nprogress-busy"),l(document.querySelector(r.parent),"nprogress-custom-parent");var t=document.getElementById("nprogress");t&&p(t)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var t=document.body.style,e="WebkitTransform"in t?"Webkit":"MozTransform"in t?"Moz":"msTransform"in t?"ms":"OTransform"in t?"O":"";return e+"Perspective"in t?"translate3d":e+"Transform"in t?"translate":"margin"};var a=function(){var t=[];function e(){var n=t.shift();n&&n(e)}return function(n){t.push(n),1==t.length&&e()}}(),s=function(){var t=["Webkit","O","Moz","ms"],e={};function n(n){return n=n.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(t,e){return e.toUpperCase()})),e[n]||(e[n]=function(e){var n=document.body.style;if(e in n)return e;for(var r,o=t.length,i=e.charAt(0).toUpperCase()+e.slice(1);o--;)if((r=t[o]+i)in n)return r;return e}(n))}function r(t,e,r){e=n(e),t.style[e]=r}return function(t,e){var n,o,i=arguments;if(2==i.length)for(n in e)void 0!==(o=e[n])&&e.hasOwnProperty(n)&&r(t,n,o);else r(t,i[1],i[2])}}();function c(t,e){return("string"==typeof t?t:f(t)).indexOf(" "+e+" ")>=0}function u(t,e){var n=f(t),r=n+e;c(n,e)||(t.className=r.substring(1))}function l(t,e){var n,r=f(t);c(t,e)&&(n=r.replace(" "+e+" "," "),t.className=n.substring(1,n.length-1))}function f(t){return(" "+(t.className||"")+" ").replace(/\s+/gi," ")}function p(t){t&&t.parentNode&&t.parentNode.removeChild(t)}return n})?r.call(e,n,e,t):r)||(t.exports=o)},function(t,e,n){"use strict";var r=n(0),o=n(45).f,i=n(12),a=n(91),s=n(33),c=n(60),u=n(119);t.exports=function(t,e){var n,l,f,p,d,h=t.target,v=t.global,m=t.stat;if(n=v?r:m?r[h]||s(h,{}):r[h]&&r[h].prototype)for(l in e){if(p=e[l],f=t.dontCallGetSet?(d=o(n,l))&&d.value:n[l],!u(v?l:h+(m?".":"#")+l,t.forced)&&void 0!==f){if(typeof p==typeof f)continue;c(p,f)}(t.sham||f&&f.sham)&&i(p,"sham",!0),a(n,l,p,t)}}},function(t,e,n){"use strict";var r=n(25),o=Function.prototype.call;t.exports=r?o.bind(o):function(){return o.apply(o,arguments)}},function(t,e,n){"use strict";var r=n(3);t.exports=!r((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")}))},function(t,e,n){"use strict";t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},function(t,e,n){"use strict";var r=n(46),o=n(28);t.exports=function(t){return r(o(t))}},function(t,e,n){"use strict";var r=n(47),o=TypeError;t.exports=function(t){if(r(t))throw new o("Can't call method on "+t);return t}},function(t,e,n){"use strict";var r=n(0),o=n(1),i=function(t){return o(t)?t:void 0};t.exports=function(t,e){return arguments.length<2?i(r[t]):r[t]&&r[t][e]}},function(t,e,n){"use strict";var r=n(1),o=n(101),i=TypeError;t.exports=function(t){if(r(t))return t;throw new i(o(t)+" is not a function")}},function(t,e,n){"use strict";var r=n(0),o=n(54),i=n(8),a=n(56),s=n(52),c=n(51),u=r.Symbol,l=o("wks"),f=c?u.for||u:u&&u.withoutSetter||a;t.exports=function(t){return i(l,t)||(l[t]=s&&i(u,t)?u[t]:f("Symbol."+t)),l[t]}},function(t,e,n){"use strict";var r=n(55),o=n(0),i=n(33),a=t.exports=o["__core-js_shared__"]||i("__core-js_shared__",{});(a.versions||(a.versions=[])).push({version:"3.37.1",mode:r?"pure":"global",copyright:"© 2014-2024 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.37.1/LICENSE",source:"https://github.com/zloirock/core-js"})},function(t,e,n){"use strict";var r=n(0),o=Object.defineProperty;t.exports=function(t,e){try{o(r,t,{value:e,configurable:!0,writable:!0})}catch(n){r[t]=e}return e}},function(t,e,n){"use strict";var r=n(28),o=Object;t.exports=function(t){return o(r(t))}},function(t,e,n){"use strict";var r=n(116);t.exports=function(t){return r(t.length)}},function(t,e,n){var r=n(143),o=n(10),i=Object.prototype,a=i.hasOwnProperty,s=i.propertyIsEnumerable,c=r(function(){return arguments}())?r:function(t){return o(t)&&a.call(t,"callee")&&!s.call(t,"callee")};t.exports=c},function(t,e,n){var r=n(9)(n(7),"Map");t.exports=r},function(t,e){t.exports=function(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}},function(t,e,n){var r=n(163),o=n(170),i=n(172),a=n(173),s=n(174);function c(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e-1&&t%1==0&&t<=9007199254740991}},function(t,e,n){var r=n(4),o=n(43),i=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,a=/^\w*$/;t.exports=function(t,e){if(r(t))return!1;var n=typeof t;return!("number"!=n&&"symbol"!=n&&"boolean"!=n&&null!=t&&!o(t))||(a.test(t)||!i.test(t)||null!=e&&t in Object(e))}},function(t,e,n){var r=n(11),o=n(10);t.exports=function(t){return"symbol"==typeof t||o(t)&&"[object Symbol]"==r(t)}},function(t,e){t.exports=function(t){return t}},function(t,e,n){"use strict";var r=n(5),o=n(24),i=n(97),a=n(26),s=n(27),c=n(48),u=n(8),l=n(57),f=Object.getOwnPropertyDescriptor;e.f=r?f:function(t,e){if(t=s(t),e=c(e),l)try{return f(t,e)}catch(t){}if(u(t,e))return a(!o(i.f,t,e),t[e])}},function(t,e,n){"use strict";var r=n(2),o=n(3),i=n(16),a=Object,s=r("".split);t.exports=o((function(){return!a("z").propertyIsEnumerable(0)}))?function(t){return"String"===i(t)?s(t,""):a(t)}:a},function(t,e,n){"use strict";t.exports=function(t){return null==t}},function(t,e,n){"use strict";var r=n(98),o=n(49);t.exports=function(t){var e=r(t,"string");return o(e)?e:e+""}},function(t,e,n){"use strict";var r=n(29),o=n(1),i=n(50),a=n(51),s=Object;t.exports=a?function(t){return"symbol"==typeof t}:function(t){var e=r("Symbol");return o(e)&&i(e.prototype,s(t))}},function(t,e,n){"use strict";var r=n(2);t.exports=r({}.isPrototypeOf)},function(t,e,n){"use strict";var r=n(52);t.exports=r&&!Symbol.sham&&"symbol"==typeof Symbol.iterator},function(t,e,n){"use strict";var r=n(53),o=n(3),i=n(0).String;t.exports=!!Object.getOwnPropertySymbols&&!o((function(){var t=Symbol("symbol detection");return!i(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&r&&r<41}))},function(t,e,n){"use strict";var r,o,i=n(0),a=n(99),s=i.process,c=i.Deno,u=s&&s.versions||c&&c.version,l=u&&u.v8;l&&(o=(r=l.split("."))[0]>0&&r[0]<4?1:+(r[0]+r[1])),!o&&a&&(!(r=a.match(/Edge\/(\d+)/))||r[1]>=74)&&(r=a.match(/Chrome\/(\d+)/))&&(o=+r[1]),t.exports=o},function(t,e,n){"use strict";var r=n(32);t.exports=function(t,e){return r[t]||(r[t]=e||{})}},function(t,e,n){"use strict";t.exports=!1},function(t,e,n){"use strict";var r=n(2),o=0,i=Math.random(),a=r(1..toString);t.exports=function(t){return"Symbol("+(void 0===t?"":t)+")_"+a(++o+i,36)}},function(t,e,n){"use strict";var r=n(5),o=n(3),i=n(103);t.exports=!r&&!o((function(){return 7!==Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a}))},function(t,e,n){"use strict";var r=n(6),o=String,i=TypeError;t.exports=function(t){if(r(t))return t;throw new i(o(t)+" is not an object")}},function(t,e,n){"use strict";t.exports={}},function(t,e,n){"use strict";var r=n(8),o=n(110),i=n(45),a=n(15);t.exports=function(t,e,n){for(var s=o(e),c=a.f,u=i.f,l=0;ll))return!1;var p=c.get(t),d=c.get(e);if(p&&d)return p==e&&d==t;var h=-1,v=!0,m=2&n?new r:void 0;for(c.set(t,e),c.set(e,t);++h-1&&t%1==0&&t=0&&Math.floor(e)===e&&isFinite(t)}function v(t){return a(t)&&"function"==typeof t.then&&"function"==typeof t.catch}function m(t){return null==t?"":Array.isArray(t)||p(t)&&t.toString===f?JSON.stringify(t,y,2):String(t)}function y(t,e){return e&&e.__v_isRef?e.value:e}function g(t){var e=parseFloat(t);return isNaN(e)?t:e}function b(t,e){for(var n=Object.create(null),r=t.split(","),o=0;o-1)return t.splice(r,1)}}var w=Object.prototype.hasOwnProperty;function O(t,e){return w.call(t,e)}function C(t){var e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}var $=/-(\w)/g,k=C((function(t){return t.replace($,(function(t,e){return e?e.toUpperCase():""}))})),S=C((function(t){return t.charAt(0).toUpperCase()+t.slice(1)})),j=/\B([A-Z])/g,E=C((function(t){return t.replace(j,"-$1").toLowerCase()}));var P=Function.prototype.bind?function(t,e){return t.bind(e)}:function(t,e){function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}return n._length=t.length,n};function A(t,e){e=e||0;for(var n=t.length-e,r=new Array(n);n--;)r[n]=t[n+e];return r}function T(t,e){for(var n in e)t[n]=e[n];return t}function L(t){for(var e={},n=0;n0,Y=J&&J.indexOf("edge/")>0;J&&J.indexOf("android");var tt=J&&/iphone|ipad|ipod|ios/.test(J);J&&/chrome\/\d+/.test(J),J&&/phantomjs/.test(J);var et,nt=J&&J.match(/firefox\/(\d+)/),rt={}.watch,ot=!1;if(Q)try{var it={};Object.defineProperty(it,"passive",{get:function(){ot=!0}}),window.addEventListener("test-passive",null,it)}catch(t){}var at=function(){return void 0===et&&(et=!Q&&"undefined"!=typeof global&&(global.process&&"server"===global.process.env.VUE_ENV)),et},st=Q&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function ct(t){return"function"==typeof t&&/native code/.test(t.toString())}var ut,lt="undefined"!=typeof Symbol&&ct(Symbol)&&"undefined"!=typeof Reflect&&ct(Reflect.ownKeys);ut="undefined"!=typeof Set&&ct(Set)?Set:function(){function t(){this.set=Object.create(null)}return t.prototype.has=function(t){return!0===this.set[t]},t.prototype.add=function(t){this.set[t]=!0},t.prototype.clear=function(){this.set=Object.create(null)},t}();var ft=null;function pt(t){void 0===t&&(t=null),t||ft&&ft._scope.off(),ft=t,t&&t._scope.on()}var dt=function(){function t(t,e,n,r,o,i,a,s){this.tag=t,this.data=e,this.children=n,this.text=r,this.elm=o,this.ns=void 0,this.context=i,this.fnContext=void 0,this.fnOptions=void 0,this.fnScopeId=void 0,this.key=e&&e.key,this.componentOptions=a,this.componentInstance=void 0,this.parent=void 0,this.raw=!1,this.isStatic=!1,this.isRootInsert=!0,this.isComment=!1,this.isCloned=!1,this.isOnce=!1,this.asyncFactory=s,this.asyncMeta=void 0,this.isAsyncPlaceholder=!1}return Object.defineProperty(t.prototype,"child",{get:function(){return this.componentInstance},enumerable:!1,configurable:!0}),t}(),ht=function(t){void 0===t&&(t="");var e=new dt;return e.text=t,e.isComment=!0,e};function vt(t){return new dt(void 0,void 0,void 0,String(t))}function mt(t){var e=new dt(t.tag,t.data,t.children&&t.children.slice(),t.text,t.elm,t.context,t.componentOptions,t.asyncFactory);return e.ns=t.ns,e.isStatic=t.isStatic,e.key=t.key,e.isComment=t.isComment,e.fnContext=t.fnContext,e.fnOptions=t.fnOptions,e.fnScopeId=t.fnScopeId,e.asyncMeta=t.asyncMeta,e.isCloned=!0,e}"function"==typeof SuppressedError&&SuppressedError;var yt=0,gt=[],bt=function(){function t(){this._pending=!1,this.id=yt++,this.subs=[]}return t.prototype.addSub=function(t){this.subs.push(t)},t.prototype.removeSub=function(t){this.subs[this.subs.indexOf(t)]=null,this._pending||(this._pending=!0,gt.push(this))},t.prototype.depend=function(e){t.target&&t.target.addDep(this)},t.prototype.notify=function(t){var e=this.subs.filter((function(t){return t}));for(var n=0,r=e.length;n0&&(Jt((u=t(u,"".concat(n||"","_").concat(r)))[0])&&Jt(f)&&(p[l]=vt(f.text+u[0].text),u.shift()),p.push.apply(p,u)):c(u)?Jt(f)?p[l]=vt(f.text+u):""!==u&&p.push(vt(u)):Jt(u)&&Jt(f)?p[l]=vt(f.text+u.text):(s(e._isVList)&&a(u.tag)&&i(u.key)&&a(n)&&(u.key="__vlist".concat(n,"_").concat(r,"__")),p.push(u)));return p}(t):void 0}function Jt(t){return a(t)&&a(t.text)&&!1===t.isComment}function Zt(t,e){var n,r,i,s,c=null;if(o(t)||"string"==typeof t)for(c=new Array(t.length),n=0,r=t.length;n0,s=e?!!e.$stable:!a,c=e&&e.$key;if(e){if(e._normalized)return e._normalized;if(s&&o&&o!==r&&c===o.$key&&!a&&!o.$hasNormal)return o;for(var u in i={},e)e[u]&&"$"!==u[0]&&(i[u]=me(t,n,u,e[u]))}else i={};for(var l in n)l in i||(i[l]=ye(n,l));return e&&Object.isExtensible(e)&&(e._normalized=i),W(i,"$stable",s),W(i,"$key",c),W(i,"$hasNormal",a),i}function me(t,e,n,r){var i=function(){var e=ft;pt(t);var n=arguments.length?r.apply(null,arguments):r({}),i=(n=n&&"object"==typeof n&&!o(n)?[n]:Qt(n))&&n[0];return pt(e),n&&(!i||1===n.length&&i.isComment&&!he(i))?void 0:n};return r.proxy&&Object.defineProperty(e,n,{get:i,enumerable:!0,configurable:!0}),i}function ye(t,e){return function(){return t[e]}}function ge(t){return{get attrs(){if(!t._attrsProxy){var e=t._attrsProxy={};W(e,"_v_attr_proxy",!0),be(e,t.$attrs,r,t,"$attrs")}return t._attrsProxy},get listeners(){t._listenersProxy||be(t._listenersProxy={},t.$listeners,r,t,"$listeners");return t._listenersProxy},get slots(){return function(t){t._slotsProxy||xe(t._slotsProxy={},t.$scopedSlots);return t._slotsProxy}(t)},emit:P(t.$emit,t),expose:function(e){e&&Object.keys(e).forEach((function(n){return Ft(t,e,n)}))}}}function be(t,e,n,r,o){var i=!1;for(var a in e)a in t?e[a]!==n[a]&&(i=!0):(i=!0,_e(t,a,r,o));for(var a in t)a in e||(i=!0,delete t[a]);return i}function _e(t,e,n,r){Object.defineProperty(t,e,{enumerable:!0,configurable:!0,get:function(){return n[r][e]}})}function xe(t,e){for(var n in e)t[n]=e[n];for(var n in t)n in e||delete t[n]}var we=null;function Oe(t,e){return(t.__esModule||lt&&"Module"===t[Symbol.toStringTag])&&(t=t.default),l(t)?e.extend(t):t}function Ce(t){if(o(t))for(var e=0;edocument.createEvent("Event").timeStamp&&(un=function(){return ln.now()})}var fn=function(t,e){if(t.post){if(!e.post)return 1}else if(e.post)return-1;return t.id-e.id};function pn(){var t,e;for(cn=un(),an=!0,en.sort(fn),sn=0;snsn&&en[n].id>t.id;)n--;en.splice(n+1,0,t)}else en.push(t);on||(on=!0,ze(pn))}}function hn(t,e){if(t){for(var n=Object.create(null),r=lt?Reflect.ownKeys(t):Object.keys(t),o=0;o-1)if(i&&!O(o,"default"))a=!1;else if(""===a||a===E(t)){var c=Mn(String,o.type);(c<0||s-1:"string"==typeof t?t.split(",").indexOf(e)>-1:!!d(t)&&t.test(e)}function Zn(t,e){var n=t.cache,r=t.keys,o=t._vnode,i=t.$vnode;for(var a in n){var s=n[a];if(s){var c=s.name;c&&!e(c)&&Xn(n,a,r,o)}}i.componentOptions.children=void 0}function Xn(t,e,n,r){var o=t[e];!o||r&&o.tag===r.tag||o.componentInstance.$destroy(),t[e]=null,x(n,e)}Gn.prototype._init=function(t){var e=this;e._uid=Hn++,e._isVue=!0,e.__v_skip=!0,e._scope=new Bt(!0),e._scope.parent=void 0,e._scope._vm=!0,t&&t._isComponent?function(t,e){var n=t.$options=Object.create(t.constructor.options),r=e._parentVnode;n.parent=e.parent,n._parentVnode=r;var o=r.componentOptions;n.propsData=o.propsData,n._parentListeners=o.listeners,n._renderChildren=o.children,n._componentTag=o.tag,e.render&&(n.render=e.render,n.staticRenderFns=e.staticRenderFns)}(e,t):e.$options=Pn(Wn(e.constructor),t||{},e),e._renderProxy=e,e._self=e,function(t){var e=t.$options,n=e.parent;if(n&&!e.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(t)}t.$parent=n,t.$root=n?n.$root:t,t.$children=[],t.$refs={},t._provided=n?n._provided:Object.create(null),t._watcher=null,t._inactive=null,t._directInactive=!1,t._isMounted=!1,t._isDestroyed=!1,t._isBeingDestroyed=!1}(e),function(t){t._events=Object.create(null),t._hasHookEvent=!1;var e=t.$options._parentListeners;e&&Qe(t,e)}(e),function(t){t._vnode=null,t._staticTrees=null;var e=t.$options,n=t.$vnode=e._parentVnode,o=n&&n.context;t.$slots=pe(e._renderChildren,o),t.$scopedSlots=n?ve(t.$parent,n.data.scopedSlots,t.$slots):r,t._c=function(e,n,r,o){return $e(t,e,n,r,o,!1)},t.$createElement=function(e,n,r,o){return $e(t,e,n,r,o,!0)};var i=n&&n.data;Tt(t,"$attrs",i&&i.attrs||r,null,!0),Tt(t,"$listeners",e._parentListeners||r,null,!0)}(e),tn(e,"beforeCreate",void 0,!1),function(t){var e=hn(t.$options.inject,t);e&&(jt(!1),Object.keys(e).forEach((function(n){Tt(t,n,e[n])})),jt(!0))}(e),zn(e),function(t){var e=t.$options.provide;if(e){var n=u(e)?e.call(t):e;if(!l(n))return;for(var r=qt(t),o=lt?Reflect.ownKeys(n):Object.keys(n),i=0;i1?A(n):n;for(var r=A(arguments,1),o='event handler for "'.concat(t,'"'),i=0,a=n.length;iparseInt(this.max)&&Xn(t,e[0],e,this._vnode),this.vnodeToCache=null}}},created:function(){this.cache=Object.create(null),this.keys=[]},destroyed:function(){for(var t in this.cache)Xn(this.cache,t,this.keys)},mounted:function(){var t=this;this.cacheVNode(),this.$watch("include",(function(e){Zn(t,(function(t){return Jn(e,t)}))})),this.$watch("exclude",(function(e){Zn(t,(function(t){return!Jn(e,t)}))}))},updated:function(){this.cacheVNode()},render:function(){var t=this.$slots.default,e=Ce(t),n=e&&e.componentOptions;if(n){var r=Qn(n),o=this.include,i=this.exclude;if(o&&(!r||!Jn(o,r))||i&&r&&Jn(i,r))return e;var a=this.cache,s=this.keys,c=null==e.key?n.Ctor.cid+(n.tag?"::".concat(n.tag):""):e.key;a[c]?(e.componentInstance=a[c].componentInstance,x(s,c),s.push(c)):(this.vnodeToCache=e,this.keyToCache=c),e.data.keepAlive=!0}return e||t&&t[0]}}};!function(t){var e={get:function(){return q}};Object.defineProperty(t,"config",e),t.util={warn:On,extend:T,mergeOptions:Pn,defineReactive:Tt},t.set=Lt,t.delete=Rt,t.nextTick=ze,t.observable=function(t){return At(t),t},t.options=Object.create(null),U.forEach((function(e){t.options[e+"s"]=Object.create(null)})),t.options._base=t,T(t.options.components,tr),function(t){t.use=function(t){var e=this._installedPlugins||(this._installedPlugins=[]);if(e.indexOf(t)>-1)return this;var n=A(arguments,1);return n.unshift(this),u(t.install)?t.install.apply(t,n):u(t)&&t.apply(null,n),e.push(t),this}}(t),function(t){t.mixin=function(t){return this.options=Pn(this.options,t),this}}(t),Kn(t),function(t){U.forEach((function(e){t[e]=function(t,n){return n?("component"===e&&p(n)&&(n.name=n.name||t,n=this.options._base.extend(n)),"directive"===e&&u(n)&&(n={bind:n,update:n}),this.options[e+"s"][t]=n,n):this.options[e+"s"][t]}}))}(t)}(Gn),Object.defineProperty(Gn.prototype,"$isServer",{get:at}),Object.defineProperty(Gn.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(Gn,"FunctionalRenderContext",{value:vn}),Gn.version="2.7.16";var er=b("style,class"),nr=b("input,textarea,option,select,progress"),rr=b("contenteditable,draggable,spellcheck"),or=b("events,caret,typing,plaintext-only"),ir=b("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,truespeed,typemustmatch,visible"),ar="http://www.w3.org/1999/xlink",sr=function(t){return":"===t.charAt(5)&&"xlink"===t.slice(0,5)},cr=function(t){return sr(t)?t.slice(6,t.length):""},ur=function(t){return null==t||!1===t};function lr(t){for(var e=t.data,n=t,r=t;a(r.componentInstance);)(r=r.componentInstance._vnode)&&r.data&&(e=fr(r.data,e));for(;a(n=n.parent);)n&&n.data&&(e=fr(e,n.data));return function(t,e){if(a(t)||a(e))return pr(t,dr(e));return""}(e.staticClass,e.class)}function fr(t,e){return{staticClass:pr(t.staticClass,e.staticClass),class:a(t.class)?[t.class,e.class]:e.class}}function pr(t,e){return t?e?t+" "+e:t:e||""}function dr(t){return Array.isArray(t)?function(t){for(var e,n="",r=0,o=t.length;r-1?Dr(t,e,n):ir(e)?ur(n)?t.removeAttribute(e):(n="allowfullscreen"===e&&"EMBED"===t.tagName?"true":e,t.setAttribute(e,n)):rr(e)?t.setAttribute(e,function(t,e){return ur(e)||"false"===e?"false":"contenteditable"===t&&or(e)?e:"true"}(e,n)):sr(e)?ur(n)?t.removeAttributeNS(ar,cr(e)):t.setAttributeNS(ar,e,n):Dr(t,e,n)}function Dr(t,e,n){if(ur(n))t.removeAttribute(e);else{if(Z&&!X&&"TEXTAREA"===t.tagName&&"placeholder"===e&&""!==n&&!t.__ieph){var r=function(e){e.stopImmediatePropagation(),t.removeEventListener("input",r)};t.addEventListener("input",r),t.__ieph=!0}t.setAttribute(e,n)}}var Nr={create:Ir,update:Ir};function zr(t,e){var n=e.elm,r=e.data,o=t.data;if(!(i(r.staticClass)&&i(r.class)&&(i(o)||i(o.staticClass)&&i(o.class)))){var s=lr(e),c=n._transitionClasses;a(c)&&(s=pr(s,dr(c))),s!==n._prevClass&&(n.setAttribute("class",s),n._prevClass=s)}}var Fr,Ur={create:zr,update:zr};function Br(t,e,n){var r=Fr;return function o(){var i=e.apply(null,arguments);null!==i&&Hr(t,o,n,r)}}var qr=Ae&&!(nt&&Number(nt[1])<=53);function Vr(t,e,n,r){if(qr){var o=cn,i=e;e=i._wrapper=function(t){if(t.target===t.currentTarget||t.timeStamp>=o||t.timeStamp<=0||t.target.ownerDocument!==document)return i.apply(this,arguments)}}Fr.addEventListener(t,e,ot?{capture:n,passive:r}:n)}function Hr(t,e,n,r){(r||Fr).removeEventListener(t,e._wrapper||e,n)}function Wr(t,e){if(!i(t.data.on)||!i(e.data.on)){var n=e.data.on||{},r=t.data.on||{};Fr=e.elm||t.elm,function(t){if(a(t.__r)){var e=Z?"change":"input";t[e]=[].concat(t.__r,t[e]||[]),delete t.__r}a(t.__c)&&(t.change=[].concat(t.__c,t.change||[]),delete t.__c)}(n),Wt(n,r,Vr,Hr,Br,e.context),Fr=void 0}}var Gr,Kr={create:Wr,update:Wr,destroy:function(t){return Wr(t,Cr)}};function Qr(t,e){if(!i(t.data.domProps)||!i(e.data.domProps)){var n,r,o=e.elm,c=t.data.domProps||{},u=e.data.domProps||{};for(n in(a(u.__ob__)||s(u._v_attr_proxy))&&(u=e.data.domProps=T({},u)),c)n in u||(o[n]="");for(n in u){if(r=u[n],"textContent"===n||"innerHTML"===n){if(e.children&&(e.children.length=0),r===c[n])continue;1===o.childNodes.length&&o.removeChild(o.childNodes[0])}if("value"===n&&"PROGRESS"!==o.tagName){o._value=r;var l=i(r)?"":String(r);Jr(o,l)&&(o.value=l)}else if("innerHTML"===n&&mr(o.tagName)&&i(o.innerHTML)){(Gr=Gr||document.createElement("div")).innerHTML="".concat(r,"");for(var f=Gr.firstChild;o.firstChild;)o.removeChild(o.firstChild);for(;f.firstChild;)o.appendChild(f.firstChild)}else if(r!==c[n])try{o[n]=r}catch(t){}}}}function Jr(t,e){return!t.composing&&("OPTION"===t.tagName||function(t,e){var n=!0;try{n=document.activeElement!==t}catch(t){}return n&&t.value!==e}(t,e)||function(t,e){var n=t.value,r=t._vModifiers;if(a(r)){if(r.number)return g(n)!==g(e);if(r.trim)return n.trim()!==e.trim()}return n!==e}(t,e))}var Zr={create:Qr,update:Qr},Xr=C((function(t){var e={},n=/:(.+)/;return t.split(/;(?![^(]*\))/g).forEach((function(t){if(t){var r=t.split(n);r.length>1&&(e[r[0].trim()]=r[1].trim())}})),e}));function Yr(t){var e=to(t.style);return t.staticStyle?T(t.staticStyle,e):e}function to(t){return Array.isArray(t)?L(t):"string"==typeof t?Xr(t):t}var eo,no=/^--/,ro=/\s*!important$/,oo=function(t,e,n){if(no.test(e))t.style.setProperty(e,n);else if(ro.test(n))t.style.setProperty(E(e),n.replace(ro,""),"important");else{var r=ao(e);if(Array.isArray(n))for(var o=0,i=n.length;o-1?e.split(uo).forEach((function(e){return t.classList.add(e)})):t.classList.add(e);else{var n=" ".concat(t.getAttribute("class")||""," ");n.indexOf(" "+e+" ")<0&&t.setAttribute("class",(n+e).trim())}}function fo(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.split(uo).forEach((function(e){return t.classList.remove(e)})):t.classList.remove(e),t.classList.length||t.removeAttribute("class");else{for(var n=" ".concat(t.getAttribute("class")||""," "),r=" "+e+" ";n.indexOf(r)>=0;)n=n.replace(r," ");(n=n.trim())?t.setAttribute("class",n):t.removeAttribute("class")}}function po(t){if(t){if("object"==typeof t){var e={};return!1!==t.css&&T(e,ho(t.name||"v")),T(e,t),e}return"string"==typeof t?ho(t):void 0}}var ho=C((function(t){return{enterClass:"".concat(t,"-enter"),enterToClass:"".concat(t,"-enter-to"),enterActiveClass:"".concat(t,"-enter-active"),leaveClass:"".concat(t,"-leave"),leaveToClass:"".concat(t,"-leave-to"),leaveActiveClass:"".concat(t,"-leave-active")}})),vo=Q&&!X,mo="transition",yo="transitionend",go="animation",bo="animationend";vo&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(mo="WebkitTransition",yo="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(go="WebkitAnimation",bo="webkitAnimationEnd"));var _o=Q?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(t){return t()};function xo(t){_o((function(){_o(t)}))}function wo(t,e){var n=t._transitionClasses||(t._transitionClasses=[]);n.indexOf(e)<0&&(n.push(e),lo(t,e))}function Oo(t,e){t._transitionClasses&&x(t._transitionClasses,e),fo(t,e)}function Co(t,e,n){var r=ko(t,e),o=r.type,i=r.timeout,a=r.propCount;if(!o)return n();var s="transition"===o?yo:bo,c=0,u=function(){t.removeEventListener(s,l),n()},l=function(e){e.target===t&&++c>=a&&u()};setTimeout((function(){c0&&(n="transition",l=a,f=i.length):"animation"===e?u>0&&(n="animation",l=u,f=c.length):f=(n=(l=Math.max(a,u))>0?a>u?"transition":"animation":null)?"transition"===n?i.length:c.length:0,{type:n,timeout:l,propCount:f,hasTransform:"transition"===n&&$o.test(r[mo+"Property"])}}function So(t,e){for(;t.length1}function Lo(t,e){!0!==e.data.show&&Eo(e)}var Ro=function(t){var e,n,r={},u=t.modules,l=t.nodeOps;for(e=0;e<$r.length;++e)for(r[$r[e]]=[],n=0;nh?_(t,i(n[y+1])?null:n[y+1].elm,n,d,y,r):d>y&&w(e,f,h)}(f,v,y,n,u):a(y)?(a(t.text)&&l.setTextContent(f,""),_(f,null,y,0,y.length-1,n)):a(v)?w(v,0,v.length-1):a(t.text)&&l.setTextContent(f,""):t.text!==e.text&&l.setTextContent(f,e.text),a(h)&&a(d=h.hook)&&a(d=d.postpatch)&&d(t,e)}}}function k(t,e,n){if(s(n)&&a(t.parent))t.parent.data.pendingInsert=e;else for(var r=0;r-1,a.selected!==i&&(a.selected=i);else if(D(zo(a),r))return void(t.selectedIndex!==s&&(t.selectedIndex=s));o||(t.selectedIndex=-1)}}function No(t,e){return e.every((function(e){return!D(e,t)}))}function zo(t){return"_value"in t?t._value:t.value}function Fo(t){t.target.composing=!0}function Uo(t){t.target.composing&&(t.target.composing=!1,Bo(t.target,"input"))}function Bo(t,e){var n=document.createEvent("HTMLEvents");n.initEvent(e,!0,!0),t.dispatchEvent(n)}function qo(t){return!t.componentInstance||t.data&&t.data.transition?t:qo(t.componentInstance._vnode)}var Vo={model:Io,show:{bind:function(t,e,n){var r=e.value,o=(n=qo(n)).data&&n.data.transition,i=t.__vOriginalDisplay="none"===t.style.display?"":t.style.display;r&&o?(n.data.show=!0,Eo(n,(function(){t.style.display=i}))):t.style.display=r?i:"none"},update:function(t,e,n){var r=e.value;!r!=!e.oldValue&&((n=qo(n)).data&&n.data.transition?(n.data.show=!0,r?Eo(n,(function(){t.style.display=t.__vOriginalDisplay})):Po(n,(function(){t.style.display="none"}))):t.style.display=r?t.__vOriginalDisplay:"none")},unbind:function(t,e,n,r,o){o||(t.style.display=t.__vOriginalDisplay)}}},Ho={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]};function Wo(t){var e=t&&t.componentOptions;return e&&e.Ctor.options.abstract?Wo(Ce(e.children)):t}function Go(t){var e={},n=t.$options;for(var r in n.propsData)e[r]=t[r];var o=n._parentListeners;for(var r in o)e[k(r)]=o[r];return e}function Ko(t,e){if(/\d-keep-alive$/.test(e.tag))return t("keep-alive",{props:e.componentOptions.propsData})}var Qo=function(t){return t.tag||he(t)},Jo=function(t){return"show"===t.name},Zo={name:"transition",props:Ho,abstract:!0,render:function(t){var e=this,n=this.$slots.default;if(n&&(n=n.filter(Qo)).length){0;var r=this.mode;0;var o=n[0];if(function(t){for(;t=t.parent;)if(t.data.transition)return!0}(this.$vnode))return o;var i=Wo(o);if(!i)return o;if(this._leaving)return Ko(t,o);var a="__transition-".concat(this._uid,"-");i.key=null==i.key?i.isComment?a+"comment":a+i.tag:c(i.key)?0===String(i.key).indexOf(a)?i.key:a+i.key:i.key;var s=(i.data||(i.data={})).transition=Go(this),u=this._vnode,l=Wo(u);if(i.data.directives&&i.data.directives.some(Jo)&&(i.data.show=!0),l&&l.data&&!function(t,e){return e.key===t.key&&e.tag===t.tag}(i,l)&&!he(l)&&(!l.componentInstance||!l.componentInstance._vnode.isComment)){var f=l.data.transition=T({},s);if("out-in"===r)return this._leaving=!0,Gt(f,"afterLeave",(function(){e._leaving=!1,e.$forceUpdate()})),Ko(t,o);if("in-out"===r){if(he(i))return u;var p,d=function(){p()};Gt(s,"afterEnter",d),Gt(s,"enterCancelled",d),Gt(f,"delayLeave",(function(t){p=t}))}}return o}}},Xo=T({tag:String,moveClass:String},Ho);function Yo(t){t.elm._moveCb&&t.elm._moveCb(),t.elm._enterCb&&t.elm._enterCb()}function ti(t){t.data.newPos=t.elm.getBoundingClientRect()}function ei(t){var e=t.data.pos,n=t.data.newPos,r=e.left-n.left,o=e.top-n.top;if(r||o){t.data.moved=!0;var i=t.elm.style;i.transform=i.WebkitTransform="translate(".concat(r,"px,").concat(o,"px)"),i.transitionDuration="0s"}}delete Xo.mode;var ni={Transition:Zo,TransitionGroup:{props:Xo,beforeMount:function(){var t=this,e=this._update;this._update=function(n,r){var o=Ze(t);t.__patch__(t._vnode,t.kept,!1,!0),t._vnode=t.kept,o(),e.call(t,n,r)}},render:function(t){for(var e=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,o=this.$slots.default||[],i=this.children=[],a=Go(this),s=0;s-1?gr[t]=e.constructor===window.HTMLUnknownElement||e.constructor===window.HTMLElement:gr[t]=/HTMLUnknownElement/.test(e.toString())},T(Gn.options.directives,Vo),T(Gn.options.components,ni),Gn.prototype.__patch__=Q?Ro:R,Gn.prototype.$mount=function(t,e){return function(t,e,n){var r;t.$el=e,t.$options.render||(t.$options.render=ht),tn(t,"beforeMount"),r=function(){t._update(t._render(),n)},new He(t,r,R,{before:function(){t._isMounted&&!t._isDestroyed&&tn(t,"beforeUpdate")}},!0),n=!1;var o=t._preWatchers;if(o)for(var i=0;i=0&&(e=t.slice(r),t=t.slice(0,r));var o=t.indexOf("?");return o>=0&&(n=t.slice(o+1),t=t.slice(0,o)),{path:t,query:n,hash:e}}(o.path||""),u=e&&e.path||"/",l=c.path?Oi(c.path,u,n||o.append):u,f=function(t,e,n){void 0===e&&(e={});var r,o=n||li;try{r=o(t||"")}catch(t){r={}}for(var i in e){var a=e[i];r[i]=Array.isArray(a)?a.map(ui):ui(a)}return r}(c.query,o.query,r&&r.options.parseQuery),p=o.hash||c.hash;return p&&"#"!==p.charAt(0)&&(p="#"+p),{_normalized:!0,path:l,query:f,hash:p}}var Vi,Hi=function(){},Wi={name:"RouterLink",props:{to:{type:[String,Object],required:!0},tag:{type:String,default:"a"},custom:Boolean,exact:Boolean,exactPath:Boolean,append:Boolean,replace:Boolean,activeClass:String,exactActiveClass:String,ariaCurrentValue:{type:String,default:"page"},event:{type:[String,Array],default:"click"}},render:function(t){var e=this,n=this.$router,r=this.$route,o=n.resolve(this.to,r,this.append),i=o.location,a=o.route,s=o.href,c={},u=n.options.linkActiveClass,l=n.options.linkExactActiveClass,f=null==u?"router-link-active":u,p=null==l?"router-link-exact-active":l,d=null==this.activeClass?f:this.activeClass,h=null==this.exactActiveClass?p:this.exactActiveClass,v=a.redirectedFrom?di(null,qi(a.redirectedFrom),null,n):a;c[h]=gi(r,v,this.exactPath),c[d]=this.exact||this.exactPath?c[h]:function(t,e){return 0===t.path.replace(pi,"/").indexOf(e.path.replace(pi,"/"))&&(!e.hash||t.hash===e.hash)&&function(t,e){for(var n in e)if(!(n in t))return!1;return!0}(t.query,e.query)}(r,v);var m=c[h]?this.ariaCurrentValue:null,y=function(t){Gi(t)&&(e.replace?n.replace(i,Hi):n.push(i,Hi))},g={click:Gi};Array.isArray(this.event)?this.event.forEach((function(t){g[t]=y})):g[this.event]=y;var b={class:c},_=!this.$scopedSlots.$hasNormal&&this.$scopedSlots.default&&this.$scopedSlots.default({href:s,route:a,navigate:y,isActive:c[d],isExactActive:c[h]});if(_){if(1===_.length)return _[0];if(_.length>1||!_.length)return 0===_.length?t():t("span",{},_)}if("a"===this.tag)b.on=g,b.attrs={href:s,"aria-current":m};else{var x=function t(e){var n;if(e)for(var r=0;r-1&&(s.params[p]=n.params[p]);return s.path=Bi(l.path,s.params),c(l,s,a)}if(s.path){s.params={};for(var d=0;d-1}function Ca(t,e){return Oa(t)&&t._isRouter&&(null==e||t.type===e)}function $a(t,e,n){var r=function(o){o>=t.length?n():t[o]?e(t[o],(function(){r(o+1)})):r(o+1)};r(0)}function ka(t){return function(e,n,r){var o=!1,i=0,a=null;Sa(t,(function(t,e,n,s){if("function"==typeof t&&void 0===t.cid){o=!0,i++;var c,u=Pa((function(e){var o;((o=e).__esModule||Ea&&"Module"===o[Symbol.toStringTag])&&(e=e.default),t.resolved="function"==typeof e?e:Vi.extend(e),n.components[s]=e,--i<=0&&r()})),l=Pa((function(t){var e="Failed to resolve async component "+s+": "+t;a||(a=Oa(t)?t:new Error(e),r(a))}));try{c=t(u,l)}catch(t){l(t)}if(c)if("function"==typeof c.then)c.then(u,l);else{var f=c.component;f&&"function"==typeof f.then&&f.then(u,l)}}})),o||r()}}function Sa(t,e){return ja(t.map((function(t){return Object.keys(t.components).map((function(n){return e(t.components[n],t.instances[n],t,n)}))})))}function ja(t){return Array.prototype.concat.apply([],t)}var Ea="function"==typeof Symbol&&"symbol"==typeof Symbol.toStringTag;function Pa(t){var e=!1;return function(){for(var n=[],r=arguments.length;r--;)n[r]=arguments[r];if(!e)return e=!0,t.apply(this,n)}}var Aa=function(t,e){this.router=t,this.base=function(t){if(!t)if(Ki){var e=document.querySelector("base");t=(t=e&&e.getAttribute("href")||"/").replace(/^https?:\/\/[^\/]+/,"")}else t="/";"/"!==t.charAt(0)&&(t="/"+t);return t.replace(/\/$/,"")}(e),this.current=vi,this.pending=null,this.ready=!1,this.readyCbs=[],this.readyErrorCbs=[],this.errorCbs=[],this.listeners=[]};function Ta(t,e,n,r){var o=Sa(t,(function(t,r,o,i){var a=function(t,e){"function"!=typeof t&&(t=Vi.extend(t));return t.options[e]}(t,e);if(a)return Array.isArray(a)?a.map((function(t){return n(t,r,o,i)})):n(a,r,o,i)}));return ja(r?o.reverse():o)}function La(t,e){if(e)return function(){return t.apply(e,arguments)}}Aa.prototype.listen=function(t){this.cb=t},Aa.prototype.onReady=function(t,e){this.ready?t():(this.readyCbs.push(t),e&&this.readyErrorCbs.push(e))},Aa.prototype.onError=function(t){this.errorCbs.push(t)},Aa.prototype.transitionTo=function(t,e,n){var r,o=this;try{r=this.router.match(t,this.current)}catch(t){throw this.errorCbs.forEach((function(e){e(t)})),t}var i=this.current;this.confirmTransition(r,(function(){o.updateRoute(r),e&&e(r),o.ensureURL(),o.router.afterHooks.forEach((function(t){t&&t(r,i)})),o.ready||(o.ready=!0,o.readyCbs.forEach((function(t){t(r)})))}),(function(t){n&&n(t),t&&!o.ready&&(Ca(t,ga.redirected)&&i===vi||(o.ready=!0,o.readyErrorCbs.forEach((function(e){e(t)}))))}))},Aa.prototype.confirmTransition=function(t,e,n){var r=this,o=this.current;this.pending=t;var i,a,s=function(t){!Ca(t)&&Oa(t)&&(r.errorCbs.length?r.errorCbs.forEach((function(e){e(t)})):console.error(t)),n&&n(t)},c=t.matched.length-1,u=o.matched.length-1;if(gi(t,o)&&c===u&&t.matched[c]===o.matched[u])return this.ensureURL(),t.hash&&aa(this.router,o,t,!1),s(((a=xa(i=o,t,ga.duplicated,'Avoided redundant navigation to current location: "'+i.fullPath+'".')).name="NavigationDuplicated",a));var l=function(t,e){var n,r=Math.max(t.length,e.length);for(n=0;n0)){var e=this.router,n=e.options.scrollBehavior,r=va&&n;r&&this.listeners.push(ia());var o=function(){var n=t.current,o=Ia(t.base);t.current===vi&&o===t._startLocation||t.transitionTo(o,(function(t){r&&aa(e,t,n,!0)}))};window.addEventListener("popstate",o),this.listeners.push((function(){window.removeEventListener("popstate",o)}))}},e.prototype.go=function(t){window.history.go(t)},e.prototype.push=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){ma(Ci(r.base+t.fullPath)),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){ya(Ci(r.base+t.fullPath)),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.ensureURL=function(t){if(Ia(this.base)!==this.current.fullPath){var e=Ci(this.base+this.current.fullPath);t?ma(e):ya(e)}},e.prototype.getCurrentLocation=function(){return Ia(this.base)},e}(Aa);function Ia(t){var e=window.location.pathname,n=e.toLowerCase(),r=t.toLowerCase();return!t||n!==r&&0!==n.indexOf(Ci(r+"/"))||(e=e.slice(t.length)),(e||"/")+window.location.search+window.location.hash}var Ma=function(t){function e(e,n,r){t.call(this,e,n),r&&function(t){var e=Ia(t);if(!/^\/#/.test(e))return window.location.replace(Ci(t+"/#"+e)),!0}(this.base)||Da()}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.setupListeners=function(){var t=this;if(!(this.listeners.length>0)){var e=this.router.options.scrollBehavior,n=va&&e;n&&this.listeners.push(ia());var r=function(){var e=t.current;Da()&&t.transitionTo(Na(),(function(r){n&&aa(t.router,r,e,!0),va||Ua(r.fullPath)}))},o=va?"popstate":"hashchange";window.addEventListener(o,r),this.listeners.push((function(){window.removeEventListener(o,r)}))}},e.prototype.push=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){Fa(t.fullPath),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){Ua(t.fullPath),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.go=function(t){window.history.go(t)},e.prototype.ensureURL=function(t){var e=this.current.fullPath;Na()!==e&&(t?Fa(e):Ua(e))},e.prototype.getCurrentLocation=function(){return Na()},e}(Aa);function Da(){var t=Na();return"/"===t.charAt(0)||(Ua("/"+t),!1)}function Na(){var t=window.location.href,e=t.indexOf("#");return e<0?"":t=t.slice(e+1)}function za(t){var e=window.location.href,n=e.indexOf("#");return(n>=0?e.slice(0,n):e)+"#"+t}function Fa(t){va?ma(za(t)):window.location.hash=t}function Ua(t){va?ya(za(t)):window.location.replace(za(t))}var Ba=function(t){function e(e,n){t.call(this,e,n),this.stack=[],this.index=-1}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.push=function(t,e,n){var r=this;this.transitionTo(t,(function(t){r.stack=r.stack.slice(0,r.index+1).concat(t),r.index++,e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var r=this;this.transitionTo(t,(function(t){r.stack=r.stack.slice(0,r.index).concat(t),e&&e(t)}),n)},e.prototype.go=function(t){var e=this,n=this.index+t;if(!(n<0||n>=this.stack.length)){var r=this.stack[n];this.confirmTransition(r,(function(){var t=e.current;e.index=n,e.updateRoute(r),e.router.afterHooks.forEach((function(e){e&&e(r,t)}))}),(function(t){Ca(t,ga.duplicated)&&(e.index=n)}))}},e.prototype.getCurrentLocation=function(){var t=this.stack[this.stack.length-1];return t?t.fullPath:"/"},e.prototype.ensureURL=function(){},e}(Aa),qa=function(t){void 0===t&&(t={}),this.app=null,this.apps=[],this.options=t,this.beforeHooks=[],this.resolveHooks=[],this.afterHooks=[],this.matcher=Zi(t.routes||[],this);var e=t.mode||"hash";switch(this.fallback="history"===e&&!va&&!1!==t.fallback,this.fallback&&(e="hash"),Ki||(e="abstract"),this.mode=e,e){case"history":this.history=new Ra(this,t.base);break;case"hash":this.history=new Ma(this,t.base,this.fallback);break;case"abstract":this.history=new Ba(this,t.base);break;default:0}},Va={currentRoute:{configurable:!0}};qa.prototype.match=function(t,e,n){return this.matcher.match(t,e,n)},Va.currentRoute.get=function(){return this.history&&this.history.current},qa.prototype.init=function(t){var e=this;if(this.apps.push(t),t.$once("hook:destroyed",(function(){var n=e.apps.indexOf(t);n>-1&&e.apps.splice(n,1),e.app===t&&(e.app=e.apps[0]||null),e.app||e.history.teardown()})),!this.app){this.app=t;var n=this.history;if(n instanceof Ra||n instanceof Ma){var r=function(t){n.setupListeners(),function(t){var r=n.current,o=e.options.scrollBehavior;va&&o&&"fullPath"in t&&aa(e,t,r,!1)}(t)};n.transitionTo(n.getCurrentLocation(),r,r)}n.listen((function(t){e.apps.forEach((function(e){e._route=t}))}))}},qa.prototype.beforeEach=function(t){return Wa(this.beforeHooks,t)},qa.prototype.beforeResolve=function(t){return Wa(this.resolveHooks,t)},qa.prototype.afterEach=function(t){return Wa(this.afterHooks,t)},qa.prototype.onReady=function(t,e){this.history.onReady(t,e)},qa.prototype.onError=function(t){this.history.onError(t)},qa.prototype.push=function(t,e,n){var r=this;if(!e&&!n&&"undefined"!=typeof Promise)return new Promise((function(e,n){r.history.push(t,e,n)}));this.history.push(t,e,n)},qa.prototype.replace=function(t,e,n){var r=this;if(!e&&!n&&"undefined"!=typeof Promise)return new Promise((function(e,n){r.history.replace(t,e,n)}));this.history.replace(t,e,n)},qa.prototype.go=function(t){this.history.go(t)},qa.prototype.back=function(){this.go(-1)},qa.prototype.forward=function(){this.go(1)},qa.prototype.getMatchedComponents=function(t){var e=t?t.matched?t:this.resolve(t).route:this.currentRoute;return e?[].concat.apply([],e.matched.map((function(t){return Object.keys(t.components).map((function(e){return t.components[e]}))}))):[]},qa.prototype.resolve=function(t,e,n){var r=qi(t,e=e||this.history.current,n,this),o=this.match(r,e),i=o.redirectedFrom||o.fullPath;return{location:r,route:o,href:function(t,e,n){var r="hash"===n?"#"+e:e;return t?Ci(t+"/"+r):r}(this.history.base,i,this.mode),normalizedTo:r,resolved:o}},qa.prototype.getRoutes=function(){return this.matcher.getRoutes()},qa.prototype.addRoute=function(t,e){this.matcher.addRoute(t,e),this.history.current!==vi&&this.history.transitionTo(this.history.getCurrentLocation())},qa.prototype.addRoutes=function(t){this.matcher.addRoutes(t),this.history.current!==vi&&this.history.transitionTo(this.history.getCurrentLocation())},Object.defineProperties(qa.prototype,Va);var Ha=qa;function Wa(t,e){return t.push(e),function(){var n=t.indexOf(e);n>-1&&t.splice(n,1)}}qa.install=function t(e){if(!t.installed||Vi!==e){t.installed=!0,Vi=e;var n=function(t){return void 0!==t},r=function(t,e){var r=t.$options._parentVnode;n(r)&&n(r=r.data)&&n(r=r.registerRouteInstance)&&r(t,e)};e.mixin({beforeCreate:function(){n(this.$options.router)?(this._routerRoot=this,this._router=this.$options.router,this._router.init(this),e.util.defineReactive(this,"_route",this._router.history.current)):this._routerRoot=this.$parent&&this.$parent._routerRoot||this,r(this,this)},destroyed:function(){r(this)}}),Object.defineProperty(e.prototype,"$router",{get:function(){return this._routerRoot._router}}),Object.defineProperty(e.prototype,"$route",{get:function(){return this._routerRoot._route}}),e.component("RouterView",xi),e.component("RouterLink",Wi);var o=e.config.optionMergeStrategies;o.beforeRouteEnter=o.beforeRouteLeave=o.beforeRouteUpdate=o.created}},qa.version="3.6.5",qa.isNavigationFailure=Ca,qa.NavigationFailureType=ga,qa.START_LOCATION=vi,Ki&&window.Vue&&window.Vue.use(qa);n(96);n(123),n(89);var Ga={"components/AlgoliaSearchBox":()=>Promise.all([n.e(0),n.e(13)]).then(n.bind(null,297)),"components/DropdownLink":()=>Promise.all([n.e(0),n.e(14)]).then(n.bind(null,254)),"components/DropdownTransition":()=>Promise.all([n.e(0),n.e(19)]).then(n.bind(null,242)),"components/Home":()=>Promise.all([n.e(0),n.e(16)]).then(n.bind(null,280)),"components/NavLink":()=>n.e(21).then(n.bind(null,241)),"components/NavLinks":()=>Promise.all([n.e(0),n.e(12)]).then(n.bind(null,265)),"components/Navbar":()=>Promise.all([n.e(0),n.e(1)]).then(n.bind(null,294)),"components/Page":()=>Promise.all([n.e(0),n.e(11)]).then(n.bind(null,281)),"components/PageEdit":()=>Promise.all([n.e(0),n.e(17)]).then(n.bind(null,267)),"components/PageNav":()=>Promise.all([n.e(0),n.e(15)]).then(n.bind(null,268)),"components/Sidebar":()=>Promise.all([n.e(0),n.e(10)]).then(n.bind(null,282)),"components/SidebarButton":()=>Promise.all([n.e(0),n.e(20)]).then(n.bind(null,283)),"components/SidebarGroup":()=>Promise.all([n.e(0),n.e(3)]).then(n.bind(null,266)),"components/SidebarLink":()=>Promise.all([n.e(0),n.e(18)]).then(n.bind(null,255)),"components/SidebarLinks":()=>Promise.all([n.e(0),n.e(3)]).then(n.bind(null,253)),"global-components/Badge":()=>Promise.all([n.e(0),n.e(4)]).then(n.bind(null,302)),"global-components/CodeBlock":()=>Promise.all([n.e(0),n.e(5)]).then(n.bind(null,298)),"global-components/CodeGroup":()=>Promise.all([n.e(0),n.e(6)]).then(n.bind(null,299)),"layouts/404":()=>n.e(7).then(n.bind(null,300)),"layouts/Layout":()=>Promise.all([n.e(0),n.e(1),n.e(2)]).then(n.bind(null,301)),NotFound:()=>n.e(7).then(n.bind(null,300)),Layout:()=>Promise.all([n.e(0),n.e(1),n.e(2)]).then(n.bind(null,301))},Ka={"v-3c88bbf2":()=>n.e(22).then(n.bind(null,303)),"v-d7e5bcfc":()=>n.e(24).then(n.bind(null,304)),"v-0decf914":()=>n.e(23).then(n.bind(null,305)),"v-c864372e":()=>n.e(25).then(n.bind(null,306)),"v-102beaee":()=>n.e(26).then(n.bind(null,307)),"v-23f0ba6e":()=>n.e(27).then(n.bind(null,308)),"v-4419f5c9":()=>n.e(28).then(n.bind(null,309)),"v-05e5796e":()=>n.e(29).then(n.bind(null,310)),"v-6d148503":()=>n.e(30).then(n.bind(null,311)),"v-70457f72":()=>n.e(31).then(n.bind(null,312)),"v-41c3bc69":()=>n.e(32).then(n.bind(null,313)),"v-2bf9c0ae":()=>n.e(33).then(n.bind(null,314)),"v-1c00b5c9":()=>n.e(34).then(n.bind(null,315)),"v-56e4d50b":()=>n.e(35).then(n.bind(null,316)),"v-87b4d6ae":()=>n.e(37).then(n.bind(null,317)),"v-4f917bd3":()=>n.e(36).then(n.bind(null,318)),"v-7bafdcee":()=>n.e(38).then(n.bind(null,319)),"v-6abbdcee":()=>n.e(39).then(n.bind(null,320)),"v-ded899ca":()=>n.e(40).then(n.bind(null,321)),"v-09883f07":()=>n.e(41).then(n.bind(null,322)),"v-300a59ee":()=>n.e(42).then(n.bind(null,323)),"v-40b685e4":()=>n.e(43).then(n.bind(null,324)),"v-a971ed74":()=>n.e(44).then(n.bind(null,325))};function Qa(t){const e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}const Ja=/-(\w)/g,Za=Qa(t=>t.replace(Ja,(t,e)=>e?e.toUpperCase():"")),Xa=/\B([A-Z])/g,Ya=Qa(t=>t.replace(Xa,"-$1").toLowerCase()),ts=Qa(t=>t.charAt(0).toUpperCase()+t.slice(1));function es(t,e){if(!e)return;if(t(e))return t(e);return e.includes("-")?t(ts(Za(e))):t(ts(e))||t(Ya(e))}const ns=Object.assign({},Ga,Ka),rs=t=>ns[t],os=t=>Ka[t],is=t=>Ga[t],as=t=>Gn.component(t);function ss(t){return es(os,t)}function cs(t){return es(is,t)}function us(t){return es(rs,t)}function ls(t){return es(as,t)}function fs(...t){return Promise.all(t.filter(t=>t).map(async t=>{if(!ls(t)&&us(t)){const e=await us(t)();Gn.component(t,e.default)}}))}function ps(t,e){"undefined"!=typeof window&&window.__VUEPRESS__&&(window.__VUEPRESS__[t]=e)}var ds=n(86),hs=n.n(ds),vs=n(87),ms=n.n(vs),ys={created(){if(this.siteMeta=this.$site.headTags.filter(([t])=>"meta"===t).map(([t,e])=>e),this.$ssrContext){const e=this.getMergedMetaTags();this.$ssrContext.title=this.$title,this.$ssrContext.lang=this.$lang,this.$ssrContext.pageMeta=(t=e)?t.map(t=>{let e="{e+=` ${n}="${ms()(t[n])}"`}),e+">"}).join("\n "):"",this.$ssrContext.canonicalLink=bs(this.$canonicalUrl)}var t},mounted(){this.currentMetaTags=[...document.querySelectorAll("meta")],this.updateMeta(),this.updateCanonicalLink()},methods:{updateMeta(){document.title=this.$title,document.documentElement.lang=this.$lang;const t=this.getMergedMetaTags();this.currentMetaTags=_s(t,this.currentMetaTags)},getMergedMetaTags(){const t=this.$page.frontmatter.meta||[];return hs()([{name:"description",content:this.$description}],t,this.siteMeta,xs)},updateCanonicalLink(){gs(),this.$canonicalUrl&&document.head.insertAdjacentHTML("beforeend",bs(this.$canonicalUrl))}},watch:{$page(){this.updateMeta(),this.updateCanonicalLink()}},beforeDestroy(){_s(null,this.currentMetaTags),gs()}};function gs(){const t=document.querySelector("link[rel='canonical']");t&&t.remove()}function bs(t=""){return t?``:""}function _s(t,e){if(e&&[...e].filter(t=>t.parentNode===document.head).forEach(t=>document.head.removeChild(t)),t)return t.map(t=>{const e=document.createElement("meta");return Object.keys(t).forEach(n=>{e.setAttribute(n,t[n])}),document.head.appendChild(e),e})}function xs(t){for(const e of["name","property","itemprop"])if(t.hasOwnProperty(e))return t[e]+e;return JSON.stringify(t)}var ws=n(88),Os={mounted(){window.addEventListener("scroll",this.onScroll)},methods:{onScroll:n.n(ws)()((function(){this.setActiveHash()}),300),setActiveHash(){const t=[].slice.call(document.querySelectorAll(".sidebar-link")),e=[].slice.call(document.querySelectorAll(".header-anchor")).filter(e=>t.some(t=>t.hash===e.hash)),n=Math.max(window.pageYOffset,document.documentElement.scrollTop,document.body.scrollTop),r=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),o=window.innerHeight+n;for(let t=0;t=i.parentElement.offsetTop+10&&(!a||n{this.$nextTick(()=>{this.$vuepress.$set("disableScrollBehavior",!1)})})}}}},beforeDestroy(){window.removeEventListener("scroll",this.onScroll)}},Cs=n(22),$s=n.n(Cs),ks=[ys,Os,{mounted(){$s.a.configure({showSpinner:!1}),this.$router.beforeEach((t,e,n)=>{t.path===e.path||Gn.component(t.name)||$s.a.start(),n()}),this.$router.afterEach(()=>{$s.a.done(),this.isSidebarOpen=!1})}}],Ss={name:"GlobalLayout",computed:{layout(){const t=this.getLayout();return ps("layout",t),Gn.component(t)}},methods:{getLayout(){if(this.$page.path){const t=this.$page.frontmatter.layout;return t&&(this.$vuepress.getLayoutAsyncComponent(t)||this.$vuepress.getVueComponent(t))?t:"Layout"}return"NotFound"}}},js=n(14),Es=Object(js.a)(Ss,(function(){return(0,this._self._c)(this.layout,{tag:"component"})}),[],!1,null,null,null).exports;!function(t,e,n){switch(e){case"components":t[e]||(t[e]={}),Object.assign(t[e],n);break;case"mixins":t[e]||(t[e]=[]),t[e].push(...n);break;default:throw new Error("Unknown option name.")}}(Es,"mixins",ks);const Ps=[{name:"v-3c88bbf2",path:"/",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-3c88bbf2").then(n)}},{path:"/index.html",redirect:"/"},{name:"v-d7e5bcfc",path:"/docs/",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-d7e5bcfc").then(n)}},{path:"/docs/index.html",redirect:"/docs/"},{name:"v-0decf914",path:"/about/",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-0decf914").then(n)}},{path:"/about/index.html",redirect:"/about/"},{name:"v-c864372e",path:"/docs/adapters.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-c864372e").then(n)}},{name:"v-102beaee",path:"/docs/client-codegen.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-102beaee").then(n)}},{name:"v-23f0ba6e",path:"/docs/client.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-23f0ba6e").then(n)}},{name:"v-4419f5c9",path:"/docs/examples.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-4419f5c9").then(n)}},{name:"v-05e5796e",path:"/docs/federation.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-05e5796e").then(n)}},{name:"v-6d148503",path:"/docs/interop.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-6d148503").then(n)}},{name:"v-70457f72",path:"/docs/introspection.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-70457f72").then(n)}},{name:"v-41c3bc69",path:"/docs/laminext.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-41c3bc69").then(n)}},{name:"v-2bf9c0ae",path:"/docs/middleware.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-2bf9c0ae").then(n)}},{name:"v-1c00b5c9",path:"/docs/optimization.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-1c00b5c9").then(n)}},{name:"v-56e4d50b",path:"/docs/relay-connections.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-56e4d50b").then(n)}},{name:"v-87b4d6ae",path:"/docs/schema-reporting.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-87b4d6ae").then(n)}},{name:"v-4f917bd3",path:"/docs/schema-comparison.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-4f917bd3").then(n)}},{name:"v-7bafdcee",path:"/docs/schema.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-7bafdcee").then(n)}},{name:"v-6abbdcee",path:"/docs/server-codegen.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-6abbdcee").then(n)}},{name:"v-ded899ca",path:"/docs/stitching.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-ded899ca").then(n)}},{name:"v-09883f07",path:"/docs/tools.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-09883f07").then(n)}},{name:"v-300a59ee",path:"/docs/validation.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-300a59ee").then(n)}},{name:"v-40b685e4",path:"/faq/",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-40b685e4").then(n)}},{path:"/faq/index.html",redirect:"/faq/"},{name:"v-a971ed74",path:"/resources/",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-a971ed74").then(n)}},{path:"/resources/index.html",redirect:"/resources/"},{path:"*",component:Es}],As={title:"",description:"",base:"/caliban/",headTags:[["link",{rel:"icon",href:"/caliban/caliban.png"}]],pages:[{title:"Home",frontmatter:{home:!0,heroImage:"/caliban.svg",actionText:"Get Started →",actionLink:"/docs/",features:[{title:"High performance",details:"While every public interface is pure and immutable, library internals have been optimized for speed."},{title:"Minimal boilerplate",details:"No need to manually define a schema for every type in your API. Let the compiler do the boring work."},{title:"Excellent interoperability",details:"Out-of-the-box support for major HTTP server libraries, effect types, Json libraries and more."}]},regularPath:"/",relativePath:"README.md",key:"v-3c88bbf2",path:"/"},{title:"Getting Started",frontmatter:{},regularPath:"/docs/",relativePath:"docs/README.md",key:"v-d7e5bcfc",path:"/docs/",headers:[{level:2,title:"A simple example",slug:"a-simple-example"},{level:2,title:"Mutations",slug:"mutations"},{level:2,title:"Subscriptions",slug:"subscriptions"},{level:2,title:"Serving over HTTP",slug:"serving-over-http"},{level:2,title:"Interop with 3rd-party libraries",slug:"interop-with-3rd-party-libraries"}]},{title:"About",frontmatter:{},regularPath:"/about/",relativePath:"about/README.md",key:"v-0decf914",path:"/about/"},{title:"Http Adapters",frontmatter:{},regularPath:"/docs/adapters.html",relativePath:"docs/adapters.md",key:"v-c864372e",path:"/docs/adapters.html",headers:[{level:2,title:"Built-in tapir adapters",slug:"built-in-tapir-adapters"},{level:2,title:"Json handling",slug:"json-handling"},{level:2,title:"Make your own adapter",slug:"make-your-own-adapter"},{level:2,title:"High-performance QuickAdapter",slug:"high-performance-quickadapter"},{level:3,title:"Usage",slug:"usage"},{level:3,title:"Customization",slug:"customization"}]},{title:"Code Generation",frontmatter:{},regularPath:"/docs/client-codegen.html",relativePath:"docs/client-codegen.md",key:"v-102beaee",path:"/docs/client-codegen.html",headers:[{level:2,title:"CalibanPlugin",slug:"calibanplugin"},{level:3,title:"From a schema file",slug:"from-a-schema-file"},{level:3,title:"From a server URL",slug:"from-a-server-url"},{level:3,title:"Generation settings",slug:"generation-settings"},{level:3,title:"Manual generation",slug:"manual-generation"},{level:2,title:"CompileTimeCalibanPlugin",slug:"compiletimecalibanplugin"},{level:3,title:"Server side configuration",slug:"server-side-configuration"},{level:3,title:"Client side configuration",slug:"client-side-configuration"},{level:3,title:"Additional information about CompileTimeCalibanPlugin",slug:"additional-information-about-compiletimecalibanplugin"}]},{title:"Getting Started",frontmatter:{},regularPath:"/docs/client.html",relativePath:"docs/client.md",key:"v-23f0ba6e",path:"/docs/client.html",headers:[{level:2,title:"Dependencies",slug:"dependencies"},{level:2,title:"Code generation",slug:"code-generation"},{level:2,title:"Query building",slug:"query-building"},{level:2,title:"Request execution",slug:"request-execution"}]},{title:"Examples",frontmatter:{},regularPath:"/docs/examples.html",relativePath:"docs/examples.md",key:"v-4419f5c9",path:"/docs/examples.html"},{title:"Federation",frontmatter:{},regularPath:"/docs/federation.html",relativePath:"docs/federation.md",key:"v-05e5796e",path:"/docs/federation.html",headers:[{level:2,title:"Dependencies",slug:"dependencies"},{level:2,title:"Federating",slug:"federating"},{level:2,title:"Tracing",slug:"tracing"},{level:2,title:"Federation V2",slug:"federation-v2"},{level:3,title:"Customizing Federation",slug:"customizing-federation"}]},{title:"Interop",frontmatter:{},regularPath:"/docs/interop.html",relativePath:"docs/interop.md",key:"v-6d148503",path:"/docs/interop.html",headers:[{level:2,title:"Cats Effect",slug:"cats-effect"},{level:2,title:"Monix (only with cats-effect 2.x)",slug:"monix-only-with-cats-effect-2-x"},{level:2,title:"Tapir",slug:"tapir"},{level:3,title:"GraphQL restrictions",slug:"graphql-restrictions"}]},{title:"Introspection",frontmatter:{},regularPath:"/docs/introspection.html",relativePath:"docs/introspection.md",key:"v-70457f72",path:"/docs/introspection.html"},{title:"Laminext Integration",frontmatter:{},regularPath:"/docs/laminext.html",relativePath:"docs/laminext.md",key:"v-41c3bc69",path:"/docs/laminext.html"},{title:"Middleware",frontmatter:{},regularPath:"/docs/middleware.html",relativePath:"docs/middleware.md",key:"v-2bf9c0ae",path:"/docs/middleware.html",headers:[{level:2,title:"Wrapper types",slug:"wrapper-types"},{level:2,title:"Pre-defined wrappers",slug:"pre-defined-wrappers"},{level:2,title:"Wrapping the interpreter",slug:"wrapping-the-interpreter"},{level:2,title:"Customizing error responses",slug:"customizing-error-responses"},{level:2,title:"Wrapping the GraphQL",slug:"wrapping-the-graphql"},{level:2,title:"Cost Estimation",slug:"cost-estimation"},{level:2,title:"OpenTelemetry Tracing",slug:"opentelemetry-tracing"}]},{title:"Query optimization",frontmatter:{},regularPath:"/docs/optimization.html",relativePath:"docs/optimization.md",key:"v-1c00b5c9",path:"/docs/optimization.html",headers:[{level:2,title:"Introducing ZQuery",slug:"introducing-zquery"},{level:2,title:"Building a DataSource",slug:"building-a-datasource"},{level:2,title:"ZQuery constructors and operators",slug:"zquery-constructors-and-operators"},{level:2,title:"Using ZQuery with Caliban",slug:"using-zquery-with-caliban"},{level:2,title:"Using field metadata",slug:"using-field-metadata"},{level:2,title:"@defer support (experimental)",slug:"defer-support-experimental"},{level:3,title:"Usage",slug:"usage"}]},{title:"Relay Connections",frontmatter:{},regularPath:"/docs/relay-connections.html",relativePath:"docs/relay-connections.md",key:"v-56e4d50b",path:"/docs/relay-connections.html",headers:[{level:2,title:"Cursors",slug:"cursors"}]},{title:"Schema Reporting",frontmatter:{},regularPath:"/docs/schema-reporting.html",relativePath:"docs/schema-reporting.md",key:"v-87b4d6ae",path:"/docs/schema-reporting.html"},{title:"Schema comparison",frontmatter:{},regularPath:"/docs/schema-comparison.html",relativePath:"docs/schema-comparison.md",key:"v-4f917bd3",path:"/docs/schema-comparison.html"},{title:"Schemas",frontmatter:{},regularPath:"/docs/schema.html",relativePath:"docs/schema.md",key:"v-7bafdcee",path:"/docs/schema.html",headers:[{level:2,title:"Enums, unions, interfaces",slug:"enums-unions-interfaces"},{level:2,title:"Case classes and sealed traits",slug:"case-classes-and-sealed-traits"},{level:3,title:"Auto derivation",slug:"auto-derivation"},{level:3,title:"Semi-auto derivation",slug:"semi-auto-derivation"},{level:3,title:"Combining auto and semi-auto derivation",slug:"combining-auto-and-semi-auto-derivation"},{level:3,title:"Deriving fields from case class methods (Scala 3 only)",slug:"deriving-fields-from-case-class-methods-scala-3-only"},{level:2,title:"Arguments",slug:"arguments"},{level:2,title:"Custom types",slug:"custom-types"},{level:2,title:"Effects",slug:"effects"},{level:2,title:"Annotations",slug:"annotations"},{level:2,title:"Java 8 Time types",slug:"java-8-time-types"},{level:2,title:"Code generation",slug:"code-generation"},{level:2,title:"Building Schemas by hand",slug:"building-schemas-by-hand"}]},{title:"Server code generation from schema",frontmatter:{},regularPath:"/docs/server-codegen.html",relativePath:"docs/server-codegen.md",key:"v-6abbdcee",path:"/docs/server-codegen.html",headers:[{level:3,title:"Lazy evaluation",slug:"lazy-evaluation"},{level:3,title:"Newtype declaration",slug:"newtype-declaration"}]},{title:"Stitching",frontmatter:{},regularPath:"/docs/stitching.html",relativePath:"docs/stitching.md",key:"v-ded899ca",path:"/docs/stitching.html",headers:[{level:2,title:"Dependencies",slug:"dependencies"},{level:2,title:"Stitching in Action",slug:"stitching-in-action"},{level:2,title:"Things not yet supported",slug:"things-not-yet-supported"}]},{title:"Getting Started",frontmatter:{},regularPath:"/docs/tools.html",relativePath:"docs/tools.md",key:"v-09883f07",path:"/docs/tools.html",headers:[{level:2,title:"Dependency",slug:"dependency"}]},{title:"Validation",frontmatter:{},regularPath:"/docs/validation.html",relativePath:"docs/validation.md",key:"v-300a59ee",path:"/docs/validation.html"},{title:"FAQ",frontmatter:{},regularPath:"/faq/",relativePath:"faq/README.md",key:"v-40b685e4",path:"/faq/",headers:[{level:3,title:"I don't know where to start 😥",slug:"i-don-t-know-where-to-start-😥"},{level:3,title:"I'm getting a compilation error saying a Schema is missing, but I don't know which one.",slug:"i-m-getting-a-compilation-error-saying-a-schema-is-missing-but-i-don-t-know-which-one"},{level:3,title:"I want to use Caliban, but I use Cats Effect / Monix instead of ZIO.",slug:"i-want-to-use-caliban-but-i-use-cats-effect-monix-instead-of-zio"},{level:3,title:'My query fails with an "Effect failure" error. How can I get more details?',slug:"my-query-fails-with-an-effect-failure-error-how-can-i-get-more-details"},{level:3,title:"I have more than 22 fields in my Query, I can't create a case class for it.",slug:"i-have-more-than-22-fields-in-my-query-i-can-t-create-a-case-class-for-it"},{level:3,title:"How to deal with authentication/authorization?",slug:"how-to-deal-with-authentication-authorization"},{level:3,title:"I have 2 case classes with the same name (different packages). How to avoid conflicts?",slug:"i-have-2-case-classes-with-the-same-name-different-packages-how-to-avoid-conflicts"},{level:3,title:"The auto-generated schema shows a field is nullable, but I want it non-nullable instead.",slug:"the-auto-generated-schema-shows-a-field-is-nullable-but-i-want-it-non-nullable-instead"},{level:3,title:"Can I use a union as input?",slug:"can-i-use-a-union-as-input"},{level:3,title:"How to deal with recursive types?",slug:"how-to-deal-with-recursive-types"},{level:3,title:'I\'m getting a "Method too large" compiler error.',slug:"i-m-getting-a-method-too-large-compiler-error"},{level:3,title:"How can I define a Schema for a Java enum?",slug:"how-can-i-define-a-schema-for-a-java-enum"},{level:3,title:"I don't want to use Throwable as my error type",slug:"i-don-t-want-to-use-throwable-as-my-error-type"},{level:3,title:"My interface is missing from the schema",slug:"my-interface-is-missing-from-the-schema"}]},{title:"Resources",frontmatter:{},regularPath:"/resources/",relativePath:"resources/README.md",key:"v-a971ed74",path:"/resources/",headers:[{level:2,title:"Talks",slug:"talks"},{level:2,title:"Blog Articles",slug:"blog-articles"},{level:2,title:"Related Projects",slug:"related-projects"}]}],themeConfig:{logo:"/caliban.svg",locales:{"/":{selectText:"Language",label:"English",nav:[{text:"Documentation",link:"/docs/"},{text:"Resources",link:"/resources/"},{text:"FAQ",link:"/faq/"},{text:"About",link:"/about/"},{text:"Github",link:"https://github.com/ghostdogpr/caliban"},{text:"Scaladoc",link:"https://javadoc.io/doc/com.github.ghostdogpr/caliban_2.12/"}],sidebar:{"/docs/":[{title:"Caliban Server",collapsable:!0,sidebarDepth:2,children:["","schema","middleware","optimization","validation","introspection","adapters","interop","federation","relay-connections","schema-reporting","server-codegen"]},{title:"Caliban Client",collapsable:!0,sidebarDepth:2,children:["client","client-codegen","laminext"]},{title:"Caliban Tools",collapsable:!0,sidebarDepth:2,children:["tools","stitching","schema-comparison"]},{title:"Examples",path:"examples"}]}}}},locales:{"/":{lang:"en-US",title:"Caliban",description:"Functional GraphQL library for Scala",path:"/"}}};n(234);Gn.component("Badge",()=>Promise.all([n.e(0),n.e(4)]).then(n.bind(null,302))),Gn.component("CodeBlock",()=>Promise.all([n.e(0),n.e(5)]).then(n.bind(null,298))),Gn.component("CodeGroup",()=>Promise.all([n.e(0),n.e(6)]).then(n.bind(null,299)));n(235);var Ts=[{},({Vue:t})=>{t.mixin({computed:{$dataBlock(){return this.$options.__data__block__}}})},{},{}],Ls=[];class Rs extends class{constructor(){this.store=new Gn({data:{state:{}}})}$get(t){return this.store.state[t]}$set(t,e){Gn.set(this.store.state,t,e)}$emit(...t){this.store.$emit(...t)}$on(...t){this.store.$on(...t)}}{}Object.assign(Rs.prototype,{getPageAsyncComponent:ss,getLayoutAsyncComponent:cs,getAsyncComponent:us,getVueComponent:ls});var Is={install(t){const e=new Rs;t.$vuepress=e,t.prototype.$vuepress=e}};function Ms(t,e){const n=e.toLowerCase();return t.options.routes.some(t=>t.path.toLowerCase()===n)}var Ds={props:{pageKey:String,slotKey:{type:String,default:"default"}},render(t){const e=this.pageKey||this.$parent.$page.key;return ps("pageKey",e),Gn.component(e)||Gn.component(e,ss(e)),Gn.component(e)?t(e):t("")}},Ns={functional:!0,props:{slotKey:String,required:!0},render:(t,{props:e,slots:n})=>t("div",{class:["content__"+e.slotKey]},n()[e.slotKey])},zs={computed:{openInNewWindowTitle(){return this.$themeLocaleConfig.openNewWindowText||"(opens new window)"}}},Fs=(n(236),n(237),Object(js.a)(zs,(function(){var t=this._self._c;return t("span",[t("svg",{staticClass:"icon outbound",attrs:{xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",x:"0px",y:"0px",viewBox:"0 0 100 100",width:"15",height:"15"}},[t("path",{attrs:{fill:"currentColor",d:"M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"}}),this._v(" "),t("polygon",{attrs:{fill:"currentColor",points:"45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"}})]),this._v(" "),t("span",{staticClass:"sr-only"},[this._v(this._s(this.openInNewWindowTitle))])])}),[],!1,null,null,null).exports),Us={functional:!0,render(t,{parent:e,children:n}){if(e._isMounted)return n;e.$once("hook:mounted",()=>{e.$forceUpdate()})}};Gn.config.productionTip=!1,Gn.use(Ha),Gn.use(Is),Gn.mixin(function(t,e,n=Gn){!function(t){t.locales&&Object.keys(t.locales).forEach(e=>{t.locales[e].path=e});Object.freeze(t)}(e),n.$vuepress.$set("siteData",e);const r=new(t(n.$vuepress.$get("siteData"))),o=Object.getOwnPropertyDescriptors(Object.getPrototypeOf(r)),i={};return Object.keys(o).reduce((t,e)=>(e.startsWith("$")&&(t[e]=o[e].get),t),i),{computed:i}}(t=>class{setPage(t){this.__page=t}get $site(){return t}get $themeConfig(){return this.$site.themeConfig}get $frontmatter(){return this.$page.frontmatter}get $localeConfig(){const{locales:t={}}=this.$site;let e,n;for(const r in t)"/"===r?n=t[r]:0===this.$page.path.indexOf(r)&&(e=t[r]);return e||n||{}}get $siteTitle(){return this.$localeConfig.title||this.$site.title||""}get $canonicalUrl(){const{canonicalUrl:t}=this.$page.frontmatter;return"string"==typeof t&&t}get $title(){const t=this.$page,{metaTitle:e}=this.$page.frontmatter;if("string"==typeof e)return e;const n=this.$siteTitle,r=t.frontmatter.home?null:t.frontmatter.title||t.title;return n?r?r+" | "+n:n:r||"VuePress"}get $description(){const t=function(t){if(t){const e=t.filter(t=>"description"===t.name)[0];if(e)return e.content}}(this.$page.frontmatter.meta);return t||(this.$page.frontmatter.description||this.$localeConfig.description||this.$site.description||"")}get $lang(){return this.$page.frontmatter.lang||this.$localeConfig.lang||"en-US"}get $localePath(){return this.$localeConfig.path||"/"}get $themeLocaleConfig(){return(this.$site.themeConfig.locales||{})[this.$localePath]||{}}get $page(){return this.__page?this.__page:function(t,e){for(let n=0;nn||(t.hash?!Gn.$vuepress.$get("disableScrollBehavior")&&{selector:decodeURIComponent(t.hash)}:{x:0,y:0})});!function(t){t.beforeEach((e,n,r)=>{if(Ms(t,e.path))r();else if(/(\/|\.html)$/.test(e.path))if(/\/$/.test(e.path)){const n=e.path.replace(/\/$/,"")+".html";Ms(t,n)?r(n):r()}else r();else{const n=e.path+"/",o=e.path+".html";Ms(t,o)?r(o):Ms(t,n)?r(n):r()}})}(n);const r={};try{await Promise.all(Ts.filter(t=>"function"==typeof t).map(e=>e({Vue:Gn,options:r,router:n,siteData:As,isServer:t})))}catch(t){console.error(t)}return{app:new Gn(Object.assign(r,{router:n,render:t=>t("div",{attrs:{id:"app"}},[t("RouterView",{ref:"layout"}),t("div",{class:"global-ui"},Ls.map(e=>t(e)))])})),router:n}}(!1).then(({app:t,router:e})=>{e.onReady(()=>{t.$mount("#app")})})}]); \ No newline at end of file +var r=Object.freeze({}),o=Array.isArray;function i(t){return null==t}function a(t){return null!=t}function s(t){return!0===t}function c(t){return"string"==typeof t||"number"==typeof t||"symbol"==typeof t||"boolean"==typeof t}function u(t){return"function"==typeof t}function l(t){return null!==t&&"object"==typeof t}var f=Object.prototype.toString;function p(t){return"[object Object]"===f.call(t)}function d(t){return"[object RegExp]"===f.call(t)}function h(t){var e=parseFloat(String(t));return e>=0&&Math.floor(e)===e&&isFinite(t)}function v(t){return a(t)&&"function"==typeof t.then&&"function"==typeof t.catch}function m(t){return null==t?"":Array.isArray(t)||p(t)&&t.toString===f?JSON.stringify(t,y,2):String(t)}function y(t,e){return e&&e.__v_isRef?e.value:e}function g(t){var e=parseFloat(t);return isNaN(e)?t:e}function b(t,e){for(var n=Object.create(null),r=t.split(","),o=0;o-1)return t.splice(r,1)}}var w=Object.prototype.hasOwnProperty;function O(t,e){return w.call(t,e)}function C(t){var e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}var $=/-(\w)/g,k=C((function(t){return t.replace($,(function(t,e){return e?e.toUpperCase():""}))})),S=C((function(t){return t.charAt(0).toUpperCase()+t.slice(1)})),j=/\B([A-Z])/g,E=C((function(t){return t.replace(j,"-$1").toLowerCase()}));var P=Function.prototype.bind?function(t,e){return t.bind(e)}:function(t,e){function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}return n._length=t.length,n};function A(t,e){e=e||0;for(var n=t.length-e,r=new Array(n);n--;)r[n]=t[n+e];return r}function T(t,e){for(var n in e)t[n]=e[n];return t}function L(t){for(var e={},n=0;n0,Y=J&&J.indexOf("edge/")>0;J&&J.indexOf("android");var tt=J&&/iphone|ipad|ipod|ios/.test(J);J&&/chrome\/\d+/.test(J),J&&/phantomjs/.test(J);var et,nt=J&&J.match(/firefox\/(\d+)/),rt={}.watch,ot=!1;if(Q)try{var it={};Object.defineProperty(it,"passive",{get:function(){ot=!0}}),window.addEventListener("test-passive",null,it)}catch(t){}var at=function(){return void 0===et&&(et=!Q&&"undefined"!=typeof global&&(global.process&&"server"===global.process.env.VUE_ENV)),et},st=Q&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function ct(t){return"function"==typeof t&&/native code/.test(t.toString())}var ut,lt="undefined"!=typeof Symbol&&ct(Symbol)&&"undefined"!=typeof Reflect&&ct(Reflect.ownKeys);ut="undefined"!=typeof Set&&ct(Set)?Set:function(){function t(){this.set=Object.create(null)}return t.prototype.has=function(t){return!0===this.set[t]},t.prototype.add=function(t){this.set[t]=!0},t.prototype.clear=function(){this.set=Object.create(null)},t}();var ft=null;function pt(t){void 0===t&&(t=null),t||ft&&ft._scope.off(),ft=t,t&&t._scope.on()}var dt=function(){function t(t,e,n,r,o,i,a,s){this.tag=t,this.data=e,this.children=n,this.text=r,this.elm=o,this.ns=void 0,this.context=i,this.fnContext=void 0,this.fnOptions=void 0,this.fnScopeId=void 0,this.key=e&&e.key,this.componentOptions=a,this.componentInstance=void 0,this.parent=void 0,this.raw=!1,this.isStatic=!1,this.isRootInsert=!0,this.isComment=!1,this.isCloned=!1,this.isOnce=!1,this.asyncFactory=s,this.asyncMeta=void 0,this.isAsyncPlaceholder=!1}return Object.defineProperty(t.prototype,"child",{get:function(){return this.componentInstance},enumerable:!1,configurable:!0}),t}(),ht=function(t){void 0===t&&(t="");var e=new dt;return e.text=t,e.isComment=!0,e};function vt(t){return new dt(void 0,void 0,void 0,String(t))}function mt(t){var e=new dt(t.tag,t.data,t.children&&t.children.slice(),t.text,t.elm,t.context,t.componentOptions,t.asyncFactory);return e.ns=t.ns,e.isStatic=t.isStatic,e.key=t.key,e.isComment=t.isComment,e.fnContext=t.fnContext,e.fnOptions=t.fnOptions,e.fnScopeId=t.fnScopeId,e.asyncMeta=t.asyncMeta,e.isCloned=!0,e}"function"==typeof SuppressedError&&SuppressedError;var yt=0,gt=[],bt=function(){function t(){this._pending=!1,this.id=yt++,this.subs=[]}return t.prototype.addSub=function(t){this.subs.push(t)},t.prototype.removeSub=function(t){this.subs[this.subs.indexOf(t)]=null,this._pending||(this._pending=!0,gt.push(this))},t.prototype.depend=function(e){t.target&&t.target.addDep(this)},t.prototype.notify=function(t){var e=this.subs.filter((function(t){return t}));for(var n=0,r=e.length;n0&&(Jt((u=t(u,"".concat(n||"","_").concat(r)))[0])&&Jt(f)&&(p[l]=vt(f.text+u[0].text),u.shift()),p.push.apply(p,u)):c(u)?Jt(f)?p[l]=vt(f.text+u):""!==u&&p.push(vt(u)):Jt(u)&&Jt(f)?p[l]=vt(f.text+u.text):(s(e._isVList)&&a(u.tag)&&i(u.key)&&a(n)&&(u.key="__vlist".concat(n,"_").concat(r,"__")),p.push(u)));return p}(t):void 0}function Jt(t){return a(t)&&a(t.text)&&!1===t.isComment}function Zt(t,e){var n,r,i,s,c=null;if(o(t)||"string"==typeof t)for(c=new Array(t.length),n=0,r=t.length;n0,s=e?!!e.$stable:!a,c=e&&e.$key;if(e){if(e._normalized)return e._normalized;if(s&&o&&o!==r&&c===o.$key&&!a&&!o.$hasNormal)return o;for(var u in i={},e)e[u]&&"$"!==u[0]&&(i[u]=me(t,n,u,e[u]))}else i={};for(var l in n)l in i||(i[l]=ye(n,l));return e&&Object.isExtensible(e)&&(e._normalized=i),W(i,"$stable",s),W(i,"$key",c),W(i,"$hasNormal",a),i}function me(t,e,n,r){var i=function(){var e=ft;pt(t);var n=arguments.length?r.apply(null,arguments):r({}),i=(n=n&&"object"==typeof n&&!o(n)?[n]:Qt(n))&&n[0];return pt(e),n&&(!i||1===n.length&&i.isComment&&!he(i))?void 0:n};return r.proxy&&Object.defineProperty(e,n,{get:i,enumerable:!0,configurable:!0}),i}function ye(t,e){return function(){return t[e]}}function ge(t){return{get attrs(){if(!t._attrsProxy){var e=t._attrsProxy={};W(e,"_v_attr_proxy",!0),be(e,t.$attrs,r,t,"$attrs")}return t._attrsProxy},get listeners(){t._listenersProxy||be(t._listenersProxy={},t.$listeners,r,t,"$listeners");return t._listenersProxy},get slots(){return function(t){t._slotsProxy||xe(t._slotsProxy={},t.$scopedSlots);return t._slotsProxy}(t)},emit:P(t.$emit,t),expose:function(e){e&&Object.keys(e).forEach((function(n){return Ft(t,e,n)}))}}}function be(t,e,n,r,o){var i=!1;for(var a in e)a in t?e[a]!==n[a]&&(i=!0):(i=!0,_e(t,a,r,o));for(var a in t)a in e||(i=!0,delete t[a]);return i}function _e(t,e,n,r){Object.defineProperty(t,e,{enumerable:!0,configurable:!0,get:function(){return n[r][e]}})}function xe(t,e){for(var n in e)t[n]=e[n];for(var n in t)n in e||delete t[n]}var we=null;function Oe(t,e){return(t.__esModule||lt&&"Module"===t[Symbol.toStringTag])&&(t=t.default),l(t)?e.extend(t):t}function Ce(t){if(o(t))for(var e=0;edocument.createEvent("Event").timeStamp&&(un=function(){return ln.now()})}var fn=function(t,e){if(t.post){if(!e.post)return 1}else if(e.post)return-1;return t.id-e.id};function pn(){var t,e;for(cn=un(),an=!0,en.sort(fn),sn=0;snsn&&en[n].id>t.id;)n--;en.splice(n+1,0,t)}else en.push(t);on||(on=!0,ze(pn))}}function hn(t,e){if(t){for(var n=Object.create(null),r=lt?Reflect.ownKeys(t):Object.keys(t),o=0;o-1)if(i&&!O(o,"default"))a=!1;else if(""===a||a===E(t)){var c=Mn(String,o.type);(c<0||s-1:"string"==typeof t?t.split(",").indexOf(e)>-1:!!d(t)&&t.test(e)}function Zn(t,e){var n=t.cache,r=t.keys,o=t._vnode,i=t.$vnode;for(var a in n){var s=n[a];if(s){var c=s.name;c&&!e(c)&&Xn(n,a,r,o)}}i.componentOptions.children=void 0}function Xn(t,e,n,r){var o=t[e];!o||r&&o.tag===r.tag||o.componentInstance.$destroy(),t[e]=null,x(n,e)}Gn.prototype._init=function(t){var e=this;e._uid=Hn++,e._isVue=!0,e.__v_skip=!0,e._scope=new Bt(!0),e._scope.parent=void 0,e._scope._vm=!0,t&&t._isComponent?function(t,e){var n=t.$options=Object.create(t.constructor.options),r=e._parentVnode;n.parent=e.parent,n._parentVnode=r;var o=r.componentOptions;n.propsData=o.propsData,n._parentListeners=o.listeners,n._renderChildren=o.children,n._componentTag=o.tag,e.render&&(n.render=e.render,n.staticRenderFns=e.staticRenderFns)}(e,t):e.$options=Pn(Wn(e.constructor),t||{},e),e._renderProxy=e,e._self=e,function(t){var e=t.$options,n=e.parent;if(n&&!e.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(t)}t.$parent=n,t.$root=n?n.$root:t,t.$children=[],t.$refs={},t._provided=n?n._provided:Object.create(null),t._watcher=null,t._inactive=null,t._directInactive=!1,t._isMounted=!1,t._isDestroyed=!1,t._isBeingDestroyed=!1}(e),function(t){t._events=Object.create(null),t._hasHookEvent=!1;var e=t.$options._parentListeners;e&&Qe(t,e)}(e),function(t){t._vnode=null,t._staticTrees=null;var e=t.$options,n=t.$vnode=e._parentVnode,o=n&&n.context;t.$slots=pe(e._renderChildren,o),t.$scopedSlots=n?ve(t.$parent,n.data.scopedSlots,t.$slots):r,t._c=function(e,n,r,o){return $e(t,e,n,r,o,!1)},t.$createElement=function(e,n,r,o){return $e(t,e,n,r,o,!0)};var i=n&&n.data;Tt(t,"$attrs",i&&i.attrs||r,null,!0),Tt(t,"$listeners",e._parentListeners||r,null,!0)}(e),tn(e,"beforeCreate",void 0,!1),function(t){var e=hn(t.$options.inject,t);e&&(jt(!1),Object.keys(e).forEach((function(n){Tt(t,n,e[n])})),jt(!0))}(e),zn(e),function(t){var e=t.$options.provide;if(e){var n=u(e)?e.call(t):e;if(!l(n))return;for(var r=qt(t),o=lt?Reflect.ownKeys(n):Object.keys(n),i=0;i1?A(n):n;for(var r=A(arguments,1),o='event handler for "'.concat(t,'"'),i=0,a=n.length;iparseInt(this.max)&&Xn(t,e[0],e,this._vnode),this.vnodeToCache=null}}},created:function(){this.cache=Object.create(null),this.keys=[]},destroyed:function(){for(var t in this.cache)Xn(this.cache,t,this.keys)},mounted:function(){var t=this;this.cacheVNode(),this.$watch("include",(function(e){Zn(t,(function(t){return Jn(e,t)}))})),this.$watch("exclude",(function(e){Zn(t,(function(t){return!Jn(e,t)}))}))},updated:function(){this.cacheVNode()},render:function(){var t=this.$slots.default,e=Ce(t),n=e&&e.componentOptions;if(n){var r=Qn(n),o=this.include,i=this.exclude;if(o&&(!r||!Jn(o,r))||i&&r&&Jn(i,r))return e;var a=this.cache,s=this.keys,c=null==e.key?n.Ctor.cid+(n.tag?"::".concat(n.tag):""):e.key;a[c]?(e.componentInstance=a[c].componentInstance,x(s,c),s.push(c)):(this.vnodeToCache=e,this.keyToCache=c),e.data.keepAlive=!0}return e||t&&t[0]}}};!function(t){var e={get:function(){return q}};Object.defineProperty(t,"config",e),t.util={warn:On,extend:T,mergeOptions:Pn,defineReactive:Tt},t.set=Lt,t.delete=Rt,t.nextTick=ze,t.observable=function(t){return At(t),t},t.options=Object.create(null),U.forEach((function(e){t.options[e+"s"]=Object.create(null)})),t.options._base=t,T(t.options.components,tr),function(t){t.use=function(t){var e=this._installedPlugins||(this._installedPlugins=[]);if(e.indexOf(t)>-1)return this;var n=A(arguments,1);return n.unshift(this),u(t.install)?t.install.apply(t,n):u(t)&&t.apply(null,n),e.push(t),this}}(t),function(t){t.mixin=function(t){return this.options=Pn(this.options,t),this}}(t),Kn(t),function(t){U.forEach((function(e){t[e]=function(t,n){return n?("component"===e&&p(n)&&(n.name=n.name||t,n=this.options._base.extend(n)),"directive"===e&&u(n)&&(n={bind:n,update:n}),this.options[e+"s"][t]=n,n):this.options[e+"s"][t]}}))}(t)}(Gn),Object.defineProperty(Gn.prototype,"$isServer",{get:at}),Object.defineProperty(Gn.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(Gn,"FunctionalRenderContext",{value:vn}),Gn.version="2.7.16";var er=b("style,class"),nr=b("input,textarea,option,select,progress"),rr=b("contenteditable,draggable,spellcheck"),or=b("events,caret,typing,plaintext-only"),ir=b("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,truespeed,typemustmatch,visible"),ar="http://www.w3.org/1999/xlink",sr=function(t){return":"===t.charAt(5)&&"xlink"===t.slice(0,5)},cr=function(t){return sr(t)?t.slice(6,t.length):""},ur=function(t){return null==t||!1===t};function lr(t){for(var e=t.data,n=t,r=t;a(r.componentInstance);)(r=r.componentInstance._vnode)&&r.data&&(e=fr(r.data,e));for(;a(n=n.parent);)n&&n.data&&(e=fr(e,n.data));return function(t,e){if(a(t)||a(e))return pr(t,dr(e));return""}(e.staticClass,e.class)}function fr(t,e){return{staticClass:pr(t.staticClass,e.staticClass),class:a(t.class)?[t.class,e.class]:e.class}}function pr(t,e){return t?e?t+" "+e:t:e||""}function dr(t){return Array.isArray(t)?function(t){for(var e,n="",r=0,o=t.length;r-1?Dr(t,e,n):ir(e)?ur(n)?t.removeAttribute(e):(n="allowfullscreen"===e&&"EMBED"===t.tagName?"true":e,t.setAttribute(e,n)):rr(e)?t.setAttribute(e,function(t,e){return ur(e)||"false"===e?"false":"contenteditable"===t&&or(e)?e:"true"}(e,n)):sr(e)?ur(n)?t.removeAttributeNS(ar,cr(e)):t.setAttributeNS(ar,e,n):Dr(t,e,n)}function Dr(t,e,n){if(ur(n))t.removeAttribute(e);else{if(Z&&!X&&"TEXTAREA"===t.tagName&&"placeholder"===e&&""!==n&&!t.__ieph){var r=function(e){e.stopImmediatePropagation(),t.removeEventListener("input",r)};t.addEventListener("input",r),t.__ieph=!0}t.setAttribute(e,n)}}var Nr={create:Ir,update:Ir};function zr(t,e){var n=e.elm,r=e.data,o=t.data;if(!(i(r.staticClass)&&i(r.class)&&(i(o)||i(o.staticClass)&&i(o.class)))){var s=lr(e),c=n._transitionClasses;a(c)&&(s=pr(s,dr(c))),s!==n._prevClass&&(n.setAttribute("class",s),n._prevClass=s)}}var Fr,Ur={create:zr,update:zr};function Br(t,e,n){var r=Fr;return function o(){var i=e.apply(null,arguments);null!==i&&Hr(t,o,n,r)}}var qr=Ae&&!(nt&&Number(nt[1])<=53);function Vr(t,e,n,r){if(qr){var o=cn,i=e;e=i._wrapper=function(t){if(t.target===t.currentTarget||t.timeStamp>=o||t.timeStamp<=0||t.target.ownerDocument!==document)return i.apply(this,arguments)}}Fr.addEventListener(t,e,ot?{capture:n,passive:r}:n)}function Hr(t,e,n,r){(r||Fr).removeEventListener(t,e._wrapper||e,n)}function Wr(t,e){if(!i(t.data.on)||!i(e.data.on)){var n=e.data.on||{},r=t.data.on||{};Fr=e.elm||t.elm,function(t){if(a(t.__r)){var e=Z?"change":"input";t[e]=[].concat(t.__r,t[e]||[]),delete t.__r}a(t.__c)&&(t.change=[].concat(t.__c,t.change||[]),delete t.__c)}(n),Wt(n,r,Vr,Hr,Br,e.context),Fr=void 0}}var Gr,Kr={create:Wr,update:Wr,destroy:function(t){return Wr(t,Cr)}};function Qr(t,e){if(!i(t.data.domProps)||!i(e.data.domProps)){var n,r,o=e.elm,c=t.data.domProps||{},u=e.data.domProps||{};for(n in(a(u.__ob__)||s(u._v_attr_proxy))&&(u=e.data.domProps=T({},u)),c)n in u||(o[n]="");for(n in u){if(r=u[n],"textContent"===n||"innerHTML"===n){if(e.children&&(e.children.length=0),r===c[n])continue;1===o.childNodes.length&&o.removeChild(o.childNodes[0])}if("value"===n&&"PROGRESS"!==o.tagName){o._value=r;var l=i(r)?"":String(r);Jr(o,l)&&(o.value=l)}else if("innerHTML"===n&&mr(o.tagName)&&i(o.innerHTML)){(Gr=Gr||document.createElement("div")).innerHTML="".concat(r,"");for(var f=Gr.firstChild;o.firstChild;)o.removeChild(o.firstChild);for(;f.firstChild;)o.appendChild(f.firstChild)}else if(r!==c[n])try{o[n]=r}catch(t){}}}}function Jr(t,e){return!t.composing&&("OPTION"===t.tagName||function(t,e){var n=!0;try{n=document.activeElement!==t}catch(t){}return n&&t.value!==e}(t,e)||function(t,e){var n=t.value,r=t._vModifiers;if(a(r)){if(r.number)return g(n)!==g(e);if(r.trim)return n.trim()!==e.trim()}return n!==e}(t,e))}var Zr={create:Qr,update:Qr},Xr=C((function(t){var e={},n=/:(.+)/;return t.split(/;(?![^(]*\))/g).forEach((function(t){if(t){var r=t.split(n);r.length>1&&(e[r[0].trim()]=r[1].trim())}})),e}));function Yr(t){var e=to(t.style);return t.staticStyle?T(t.staticStyle,e):e}function to(t){return Array.isArray(t)?L(t):"string"==typeof t?Xr(t):t}var eo,no=/^--/,ro=/\s*!important$/,oo=function(t,e,n){if(no.test(e))t.style.setProperty(e,n);else if(ro.test(n))t.style.setProperty(E(e),n.replace(ro,""),"important");else{var r=ao(e);if(Array.isArray(n))for(var o=0,i=n.length;o-1?e.split(uo).forEach((function(e){return t.classList.add(e)})):t.classList.add(e);else{var n=" ".concat(t.getAttribute("class")||""," ");n.indexOf(" "+e+" ")<0&&t.setAttribute("class",(n+e).trim())}}function fo(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.split(uo).forEach((function(e){return t.classList.remove(e)})):t.classList.remove(e),t.classList.length||t.removeAttribute("class");else{for(var n=" ".concat(t.getAttribute("class")||""," "),r=" "+e+" ";n.indexOf(r)>=0;)n=n.replace(r," ");(n=n.trim())?t.setAttribute("class",n):t.removeAttribute("class")}}function po(t){if(t){if("object"==typeof t){var e={};return!1!==t.css&&T(e,ho(t.name||"v")),T(e,t),e}return"string"==typeof t?ho(t):void 0}}var ho=C((function(t){return{enterClass:"".concat(t,"-enter"),enterToClass:"".concat(t,"-enter-to"),enterActiveClass:"".concat(t,"-enter-active"),leaveClass:"".concat(t,"-leave"),leaveToClass:"".concat(t,"-leave-to"),leaveActiveClass:"".concat(t,"-leave-active")}})),vo=Q&&!X,mo="transition",yo="transitionend",go="animation",bo="animationend";vo&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(mo="WebkitTransition",yo="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(go="WebkitAnimation",bo="webkitAnimationEnd"));var _o=Q?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(t){return t()};function xo(t){_o((function(){_o(t)}))}function wo(t,e){var n=t._transitionClasses||(t._transitionClasses=[]);n.indexOf(e)<0&&(n.push(e),lo(t,e))}function Oo(t,e){t._transitionClasses&&x(t._transitionClasses,e),fo(t,e)}function Co(t,e,n){var r=ko(t,e),o=r.type,i=r.timeout,a=r.propCount;if(!o)return n();var s="transition"===o?yo:bo,c=0,u=function(){t.removeEventListener(s,l),n()},l=function(e){e.target===t&&++c>=a&&u()};setTimeout((function(){c0&&(n="transition",l=a,f=i.length):"animation"===e?u>0&&(n="animation",l=u,f=c.length):f=(n=(l=Math.max(a,u))>0?a>u?"transition":"animation":null)?"transition"===n?i.length:c.length:0,{type:n,timeout:l,propCount:f,hasTransform:"transition"===n&&$o.test(r[mo+"Property"])}}function So(t,e){for(;t.length1}function Lo(t,e){!0!==e.data.show&&Eo(e)}var Ro=function(t){var e,n,r={},u=t.modules,l=t.nodeOps;for(e=0;e<$r.length;++e)for(r[$r[e]]=[],n=0;nh?_(t,i(n[y+1])?null:n[y+1].elm,n,d,y,r):d>y&&w(e,f,h)}(f,v,y,n,u):a(y)?(a(t.text)&&l.setTextContent(f,""),_(f,null,y,0,y.length-1,n)):a(v)?w(v,0,v.length-1):a(t.text)&&l.setTextContent(f,""):t.text!==e.text&&l.setTextContent(f,e.text),a(h)&&a(d=h.hook)&&a(d=d.postpatch)&&d(t,e)}}}function k(t,e,n){if(s(n)&&a(t.parent))t.parent.data.pendingInsert=e;else for(var r=0;r-1,a.selected!==i&&(a.selected=i);else if(D(zo(a),r))return void(t.selectedIndex!==s&&(t.selectedIndex=s));o||(t.selectedIndex=-1)}}function No(t,e){return e.every((function(e){return!D(e,t)}))}function zo(t){return"_value"in t?t._value:t.value}function Fo(t){t.target.composing=!0}function Uo(t){t.target.composing&&(t.target.composing=!1,Bo(t.target,"input"))}function Bo(t,e){var n=document.createEvent("HTMLEvents");n.initEvent(e,!0,!0),t.dispatchEvent(n)}function qo(t){return!t.componentInstance||t.data&&t.data.transition?t:qo(t.componentInstance._vnode)}var Vo={model:Io,show:{bind:function(t,e,n){var r=e.value,o=(n=qo(n)).data&&n.data.transition,i=t.__vOriginalDisplay="none"===t.style.display?"":t.style.display;r&&o?(n.data.show=!0,Eo(n,(function(){t.style.display=i}))):t.style.display=r?i:"none"},update:function(t,e,n){var r=e.value;!r!=!e.oldValue&&((n=qo(n)).data&&n.data.transition?(n.data.show=!0,r?Eo(n,(function(){t.style.display=t.__vOriginalDisplay})):Po(n,(function(){t.style.display="none"}))):t.style.display=r?t.__vOriginalDisplay:"none")},unbind:function(t,e,n,r,o){o||(t.style.display=t.__vOriginalDisplay)}}},Ho={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]};function Wo(t){var e=t&&t.componentOptions;return e&&e.Ctor.options.abstract?Wo(Ce(e.children)):t}function Go(t){var e={},n=t.$options;for(var r in n.propsData)e[r]=t[r];var o=n._parentListeners;for(var r in o)e[k(r)]=o[r];return e}function Ko(t,e){if(/\d-keep-alive$/.test(e.tag))return t("keep-alive",{props:e.componentOptions.propsData})}var Qo=function(t){return t.tag||he(t)},Jo=function(t){return"show"===t.name},Zo={name:"transition",props:Ho,abstract:!0,render:function(t){var e=this,n=this.$slots.default;if(n&&(n=n.filter(Qo)).length){0;var r=this.mode;0;var o=n[0];if(function(t){for(;t=t.parent;)if(t.data.transition)return!0}(this.$vnode))return o;var i=Wo(o);if(!i)return o;if(this._leaving)return Ko(t,o);var a="__transition-".concat(this._uid,"-");i.key=null==i.key?i.isComment?a+"comment":a+i.tag:c(i.key)?0===String(i.key).indexOf(a)?i.key:a+i.key:i.key;var s=(i.data||(i.data={})).transition=Go(this),u=this._vnode,l=Wo(u);if(i.data.directives&&i.data.directives.some(Jo)&&(i.data.show=!0),l&&l.data&&!function(t,e){return e.key===t.key&&e.tag===t.tag}(i,l)&&!he(l)&&(!l.componentInstance||!l.componentInstance._vnode.isComment)){var f=l.data.transition=T({},s);if("out-in"===r)return this._leaving=!0,Gt(f,"afterLeave",(function(){e._leaving=!1,e.$forceUpdate()})),Ko(t,o);if("in-out"===r){if(he(i))return u;var p,d=function(){p()};Gt(s,"afterEnter",d),Gt(s,"enterCancelled",d),Gt(f,"delayLeave",(function(t){p=t}))}}return o}}},Xo=T({tag:String,moveClass:String},Ho);function Yo(t){t.elm._moveCb&&t.elm._moveCb(),t.elm._enterCb&&t.elm._enterCb()}function ti(t){t.data.newPos=t.elm.getBoundingClientRect()}function ei(t){var e=t.data.pos,n=t.data.newPos,r=e.left-n.left,o=e.top-n.top;if(r||o){t.data.moved=!0;var i=t.elm.style;i.transform=i.WebkitTransform="translate(".concat(r,"px,").concat(o,"px)"),i.transitionDuration="0s"}}delete Xo.mode;var ni={Transition:Zo,TransitionGroup:{props:Xo,beforeMount:function(){var t=this,e=this._update;this._update=function(n,r){var o=Ze(t);t.__patch__(t._vnode,t.kept,!1,!0),t._vnode=t.kept,o(),e.call(t,n,r)}},render:function(t){for(var e=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,o=this.$slots.default||[],i=this.children=[],a=Go(this),s=0;s-1?gr[t]=e.constructor===window.HTMLUnknownElement||e.constructor===window.HTMLElement:gr[t]=/HTMLUnknownElement/.test(e.toString())},T(Gn.options.directives,Vo),T(Gn.options.components,ni),Gn.prototype.__patch__=Q?Ro:R,Gn.prototype.$mount=function(t,e){return function(t,e,n){var r;t.$el=e,t.$options.render||(t.$options.render=ht),tn(t,"beforeMount"),r=function(){t._update(t._render(),n)},new He(t,r,R,{before:function(){t._isMounted&&!t._isDestroyed&&tn(t,"beforeUpdate")}},!0),n=!1;var o=t._preWatchers;if(o)for(var i=0;i=0&&(e=t.slice(r),t=t.slice(0,r));var o=t.indexOf("?");return o>=0&&(n=t.slice(o+1),t=t.slice(0,o)),{path:t,query:n,hash:e}}(o.path||""),u=e&&e.path||"/",l=c.path?Oi(c.path,u,n||o.append):u,f=function(t,e,n){void 0===e&&(e={});var r,o=n||li;try{r=o(t||"")}catch(t){r={}}for(var i in e){var a=e[i];r[i]=Array.isArray(a)?a.map(ui):ui(a)}return r}(c.query,o.query,r&&r.options.parseQuery),p=o.hash||c.hash;return p&&"#"!==p.charAt(0)&&(p="#"+p),{_normalized:!0,path:l,query:f,hash:p}}var Vi,Hi=function(){},Wi={name:"RouterLink",props:{to:{type:[String,Object],required:!0},tag:{type:String,default:"a"},custom:Boolean,exact:Boolean,exactPath:Boolean,append:Boolean,replace:Boolean,activeClass:String,exactActiveClass:String,ariaCurrentValue:{type:String,default:"page"},event:{type:[String,Array],default:"click"}},render:function(t){var e=this,n=this.$router,r=this.$route,o=n.resolve(this.to,r,this.append),i=o.location,a=o.route,s=o.href,c={},u=n.options.linkActiveClass,l=n.options.linkExactActiveClass,f=null==u?"router-link-active":u,p=null==l?"router-link-exact-active":l,d=null==this.activeClass?f:this.activeClass,h=null==this.exactActiveClass?p:this.exactActiveClass,v=a.redirectedFrom?di(null,qi(a.redirectedFrom),null,n):a;c[h]=gi(r,v,this.exactPath),c[d]=this.exact||this.exactPath?c[h]:function(t,e){return 0===t.path.replace(pi,"/").indexOf(e.path.replace(pi,"/"))&&(!e.hash||t.hash===e.hash)&&function(t,e){for(var n in e)if(!(n in t))return!1;return!0}(t.query,e.query)}(r,v);var m=c[h]?this.ariaCurrentValue:null,y=function(t){Gi(t)&&(e.replace?n.replace(i,Hi):n.push(i,Hi))},g={click:Gi};Array.isArray(this.event)?this.event.forEach((function(t){g[t]=y})):g[this.event]=y;var b={class:c},_=!this.$scopedSlots.$hasNormal&&this.$scopedSlots.default&&this.$scopedSlots.default({href:s,route:a,navigate:y,isActive:c[d],isExactActive:c[h]});if(_){if(1===_.length)return _[0];if(_.length>1||!_.length)return 0===_.length?t():t("span",{},_)}if("a"===this.tag)b.on=g,b.attrs={href:s,"aria-current":m};else{var x=function t(e){var n;if(e)for(var r=0;r-1&&(s.params[p]=n.params[p]);return s.path=Bi(l.path,s.params),c(l,s,a)}if(s.path){s.params={};for(var d=0;d-1}function Ca(t,e){return Oa(t)&&t._isRouter&&(null==e||t.type===e)}function $a(t,e,n){var r=function(o){o>=t.length?n():t[o]?e(t[o],(function(){r(o+1)})):r(o+1)};r(0)}function ka(t){return function(e,n,r){var o=!1,i=0,a=null;Sa(t,(function(t,e,n,s){if("function"==typeof t&&void 0===t.cid){o=!0,i++;var c,u=Pa((function(e){var o;((o=e).__esModule||Ea&&"Module"===o[Symbol.toStringTag])&&(e=e.default),t.resolved="function"==typeof e?e:Vi.extend(e),n.components[s]=e,--i<=0&&r()})),l=Pa((function(t){var e="Failed to resolve async component "+s+": "+t;a||(a=Oa(t)?t:new Error(e),r(a))}));try{c=t(u,l)}catch(t){l(t)}if(c)if("function"==typeof c.then)c.then(u,l);else{var f=c.component;f&&"function"==typeof f.then&&f.then(u,l)}}})),o||r()}}function Sa(t,e){return ja(t.map((function(t){return Object.keys(t.components).map((function(n){return e(t.components[n],t.instances[n],t,n)}))})))}function ja(t){return Array.prototype.concat.apply([],t)}var Ea="function"==typeof Symbol&&"symbol"==typeof Symbol.toStringTag;function Pa(t){var e=!1;return function(){for(var n=[],r=arguments.length;r--;)n[r]=arguments[r];if(!e)return e=!0,t.apply(this,n)}}var Aa=function(t,e){this.router=t,this.base=function(t){if(!t)if(Ki){var e=document.querySelector("base");t=(t=e&&e.getAttribute("href")||"/").replace(/^https?:\/\/[^\/]+/,"")}else t="/";"/"!==t.charAt(0)&&(t="/"+t);return t.replace(/\/$/,"")}(e),this.current=vi,this.pending=null,this.ready=!1,this.readyCbs=[],this.readyErrorCbs=[],this.errorCbs=[],this.listeners=[]};function Ta(t,e,n,r){var o=Sa(t,(function(t,r,o,i){var a=function(t,e){"function"!=typeof t&&(t=Vi.extend(t));return t.options[e]}(t,e);if(a)return Array.isArray(a)?a.map((function(t){return n(t,r,o,i)})):n(a,r,o,i)}));return ja(r?o.reverse():o)}function La(t,e){if(e)return function(){return t.apply(e,arguments)}}Aa.prototype.listen=function(t){this.cb=t},Aa.prototype.onReady=function(t,e){this.ready?t():(this.readyCbs.push(t),e&&this.readyErrorCbs.push(e))},Aa.prototype.onError=function(t){this.errorCbs.push(t)},Aa.prototype.transitionTo=function(t,e,n){var r,o=this;try{r=this.router.match(t,this.current)}catch(t){throw this.errorCbs.forEach((function(e){e(t)})),t}var i=this.current;this.confirmTransition(r,(function(){o.updateRoute(r),e&&e(r),o.ensureURL(),o.router.afterHooks.forEach((function(t){t&&t(r,i)})),o.ready||(o.ready=!0,o.readyCbs.forEach((function(t){t(r)})))}),(function(t){n&&n(t),t&&!o.ready&&(Ca(t,ga.redirected)&&i===vi||(o.ready=!0,o.readyErrorCbs.forEach((function(e){e(t)}))))}))},Aa.prototype.confirmTransition=function(t,e,n){var r=this,o=this.current;this.pending=t;var i,a,s=function(t){!Ca(t)&&Oa(t)&&(r.errorCbs.length?r.errorCbs.forEach((function(e){e(t)})):console.error(t)),n&&n(t)},c=t.matched.length-1,u=o.matched.length-1;if(gi(t,o)&&c===u&&t.matched[c]===o.matched[u])return this.ensureURL(),t.hash&&aa(this.router,o,t,!1),s(((a=xa(i=o,t,ga.duplicated,'Avoided redundant navigation to current location: "'+i.fullPath+'".')).name="NavigationDuplicated",a));var l=function(t,e){var n,r=Math.max(t.length,e.length);for(n=0;n0)){var e=this.router,n=e.options.scrollBehavior,r=va&&n;r&&this.listeners.push(ia());var o=function(){var n=t.current,o=Ia(t.base);t.current===vi&&o===t._startLocation||t.transitionTo(o,(function(t){r&&aa(e,t,n,!0)}))};window.addEventListener("popstate",o),this.listeners.push((function(){window.removeEventListener("popstate",o)}))}},e.prototype.go=function(t){window.history.go(t)},e.prototype.push=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){ma(Ci(r.base+t.fullPath)),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){ya(Ci(r.base+t.fullPath)),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.ensureURL=function(t){if(Ia(this.base)!==this.current.fullPath){var e=Ci(this.base+this.current.fullPath);t?ma(e):ya(e)}},e.prototype.getCurrentLocation=function(){return Ia(this.base)},e}(Aa);function Ia(t){var e=window.location.pathname,n=e.toLowerCase(),r=t.toLowerCase();return!t||n!==r&&0!==n.indexOf(Ci(r+"/"))||(e=e.slice(t.length)),(e||"/")+window.location.search+window.location.hash}var Ma=function(t){function e(e,n,r){t.call(this,e,n),r&&function(t){var e=Ia(t);if(!/^\/#/.test(e))return window.location.replace(Ci(t+"/#"+e)),!0}(this.base)||Da()}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.setupListeners=function(){var t=this;if(!(this.listeners.length>0)){var e=this.router.options.scrollBehavior,n=va&&e;n&&this.listeners.push(ia());var r=function(){var e=t.current;Da()&&t.transitionTo(Na(),(function(r){n&&aa(t.router,r,e,!0),va||Ua(r.fullPath)}))},o=va?"popstate":"hashchange";window.addEventListener(o,r),this.listeners.push((function(){window.removeEventListener(o,r)}))}},e.prototype.push=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){Fa(t.fullPath),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){Ua(t.fullPath),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.go=function(t){window.history.go(t)},e.prototype.ensureURL=function(t){var e=this.current.fullPath;Na()!==e&&(t?Fa(e):Ua(e))},e.prototype.getCurrentLocation=function(){return Na()},e}(Aa);function Da(){var t=Na();return"/"===t.charAt(0)||(Ua("/"+t),!1)}function Na(){var t=window.location.href,e=t.indexOf("#");return e<0?"":t=t.slice(e+1)}function za(t){var e=window.location.href,n=e.indexOf("#");return(n>=0?e.slice(0,n):e)+"#"+t}function Fa(t){va?ma(za(t)):window.location.hash=t}function Ua(t){va?ya(za(t)):window.location.replace(za(t))}var Ba=function(t){function e(e,n){t.call(this,e,n),this.stack=[],this.index=-1}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.push=function(t,e,n){var r=this;this.transitionTo(t,(function(t){r.stack=r.stack.slice(0,r.index+1).concat(t),r.index++,e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var r=this;this.transitionTo(t,(function(t){r.stack=r.stack.slice(0,r.index).concat(t),e&&e(t)}),n)},e.prototype.go=function(t){var e=this,n=this.index+t;if(!(n<0||n>=this.stack.length)){var r=this.stack[n];this.confirmTransition(r,(function(){var t=e.current;e.index=n,e.updateRoute(r),e.router.afterHooks.forEach((function(e){e&&e(r,t)}))}),(function(t){Ca(t,ga.duplicated)&&(e.index=n)}))}},e.prototype.getCurrentLocation=function(){var t=this.stack[this.stack.length-1];return t?t.fullPath:"/"},e.prototype.ensureURL=function(){},e}(Aa),qa=function(t){void 0===t&&(t={}),this.app=null,this.apps=[],this.options=t,this.beforeHooks=[],this.resolveHooks=[],this.afterHooks=[],this.matcher=Zi(t.routes||[],this);var e=t.mode||"hash";switch(this.fallback="history"===e&&!va&&!1!==t.fallback,this.fallback&&(e="hash"),Ki||(e="abstract"),this.mode=e,e){case"history":this.history=new Ra(this,t.base);break;case"hash":this.history=new Ma(this,t.base,this.fallback);break;case"abstract":this.history=new Ba(this,t.base);break;default:0}},Va={currentRoute:{configurable:!0}};qa.prototype.match=function(t,e,n){return this.matcher.match(t,e,n)},Va.currentRoute.get=function(){return this.history&&this.history.current},qa.prototype.init=function(t){var e=this;if(this.apps.push(t),t.$once("hook:destroyed",(function(){var n=e.apps.indexOf(t);n>-1&&e.apps.splice(n,1),e.app===t&&(e.app=e.apps[0]||null),e.app||e.history.teardown()})),!this.app){this.app=t;var n=this.history;if(n instanceof Ra||n instanceof Ma){var r=function(t){n.setupListeners(),function(t){var r=n.current,o=e.options.scrollBehavior;va&&o&&"fullPath"in t&&aa(e,t,r,!1)}(t)};n.transitionTo(n.getCurrentLocation(),r,r)}n.listen((function(t){e.apps.forEach((function(e){e._route=t}))}))}},qa.prototype.beforeEach=function(t){return Wa(this.beforeHooks,t)},qa.prototype.beforeResolve=function(t){return Wa(this.resolveHooks,t)},qa.prototype.afterEach=function(t){return Wa(this.afterHooks,t)},qa.prototype.onReady=function(t,e){this.history.onReady(t,e)},qa.prototype.onError=function(t){this.history.onError(t)},qa.prototype.push=function(t,e,n){var r=this;if(!e&&!n&&"undefined"!=typeof Promise)return new Promise((function(e,n){r.history.push(t,e,n)}));this.history.push(t,e,n)},qa.prototype.replace=function(t,e,n){var r=this;if(!e&&!n&&"undefined"!=typeof Promise)return new Promise((function(e,n){r.history.replace(t,e,n)}));this.history.replace(t,e,n)},qa.prototype.go=function(t){this.history.go(t)},qa.prototype.back=function(){this.go(-1)},qa.prototype.forward=function(){this.go(1)},qa.prototype.getMatchedComponents=function(t){var e=t?t.matched?t:this.resolve(t).route:this.currentRoute;return e?[].concat.apply([],e.matched.map((function(t){return Object.keys(t.components).map((function(e){return t.components[e]}))}))):[]},qa.prototype.resolve=function(t,e,n){var r=qi(t,e=e||this.history.current,n,this),o=this.match(r,e),i=o.redirectedFrom||o.fullPath;return{location:r,route:o,href:function(t,e,n){var r="hash"===n?"#"+e:e;return t?Ci(t+"/"+r):r}(this.history.base,i,this.mode),normalizedTo:r,resolved:o}},qa.prototype.getRoutes=function(){return this.matcher.getRoutes()},qa.prototype.addRoute=function(t,e){this.matcher.addRoute(t,e),this.history.current!==vi&&this.history.transitionTo(this.history.getCurrentLocation())},qa.prototype.addRoutes=function(t){this.matcher.addRoutes(t),this.history.current!==vi&&this.history.transitionTo(this.history.getCurrentLocation())},Object.defineProperties(qa.prototype,Va);var Ha=qa;function Wa(t,e){return t.push(e),function(){var n=t.indexOf(e);n>-1&&t.splice(n,1)}}qa.install=function t(e){if(!t.installed||Vi!==e){t.installed=!0,Vi=e;var n=function(t){return void 0!==t},r=function(t,e){var r=t.$options._parentVnode;n(r)&&n(r=r.data)&&n(r=r.registerRouteInstance)&&r(t,e)};e.mixin({beforeCreate:function(){n(this.$options.router)?(this._routerRoot=this,this._router=this.$options.router,this._router.init(this),e.util.defineReactive(this,"_route",this._router.history.current)):this._routerRoot=this.$parent&&this.$parent._routerRoot||this,r(this,this)},destroyed:function(){r(this)}}),Object.defineProperty(e.prototype,"$router",{get:function(){return this._routerRoot._router}}),Object.defineProperty(e.prototype,"$route",{get:function(){return this._routerRoot._route}}),e.component("RouterView",xi),e.component("RouterLink",Wi);var o=e.config.optionMergeStrategies;o.beforeRouteEnter=o.beforeRouteLeave=o.beforeRouteUpdate=o.created}},qa.version="3.6.5",qa.isNavigationFailure=Ca,qa.NavigationFailureType=ga,qa.START_LOCATION=vi,Ki&&window.Vue&&window.Vue.use(qa);n(96);n(123),n(89);var Ga={"components/AlgoliaSearchBox":()=>Promise.all([n.e(0),n.e(13)]).then(n.bind(null,297)),"components/DropdownLink":()=>Promise.all([n.e(0),n.e(14)]).then(n.bind(null,254)),"components/DropdownTransition":()=>Promise.all([n.e(0),n.e(19)]).then(n.bind(null,242)),"components/Home":()=>Promise.all([n.e(0),n.e(16)]).then(n.bind(null,280)),"components/NavLink":()=>n.e(21).then(n.bind(null,241)),"components/NavLinks":()=>Promise.all([n.e(0),n.e(12)]).then(n.bind(null,265)),"components/Navbar":()=>Promise.all([n.e(0),n.e(1)]).then(n.bind(null,294)),"components/Page":()=>Promise.all([n.e(0),n.e(11)]).then(n.bind(null,281)),"components/PageEdit":()=>Promise.all([n.e(0),n.e(17)]).then(n.bind(null,267)),"components/PageNav":()=>Promise.all([n.e(0),n.e(15)]).then(n.bind(null,268)),"components/Sidebar":()=>Promise.all([n.e(0),n.e(10)]).then(n.bind(null,282)),"components/SidebarButton":()=>Promise.all([n.e(0),n.e(20)]).then(n.bind(null,283)),"components/SidebarGroup":()=>Promise.all([n.e(0),n.e(3)]).then(n.bind(null,266)),"components/SidebarLink":()=>Promise.all([n.e(0),n.e(18)]).then(n.bind(null,255)),"components/SidebarLinks":()=>Promise.all([n.e(0),n.e(3)]).then(n.bind(null,253)),"global-components/Badge":()=>Promise.all([n.e(0),n.e(4)]).then(n.bind(null,302)),"global-components/CodeBlock":()=>Promise.all([n.e(0),n.e(5)]).then(n.bind(null,298)),"global-components/CodeGroup":()=>Promise.all([n.e(0),n.e(6)]).then(n.bind(null,299)),"layouts/404":()=>n.e(7).then(n.bind(null,300)),"layouts/Layout":()=>Promise.all([n.e(0),n.e(1),n.e(2)]).then(n.bind(null,301)),NotFound:()=>n.e(7).then(n.bind(null,300)),Layout:()=>Promise.all([n.e(0),n.e(1),n.e(2)]).then(n.bind(null,301))},Ka={"v-3c88bbf2":()=>n.e(22).then(n.bind(null,303)),"v-0decf914":()=>n.e(23).then(n.bind(null,304)),"v-d7e5bcfc":()=>n.e(24).then(n.bind(null,305)),"v-c864372e":()=>n.e(25).then(n.bind(null,306)),"v-102beaee":()=>n.e(26).then(n.bind(null,307)),"v-23f0ba6e":()=>n.e(27).then(n.bind(null,308)),"v-4419f5c9":()=>n.e(28).then(n.bind(null,309)),"v-05e5796e":()=>n.e(29).then(n.bind(null,310)),"v-6d148503":()=>n.e(30).then(n.bind(null,311)),"v-41c3bc69":()=>n.e(31).then(n.bind(null,312)),"v-2bf9c0ae":()=>n.e(32).then(n.bind(null,313)),"v-1c00b5c9":()=>n.e(33).then(n.bind(null,314)),"v-56e4d50b":()=>n.e(34).then(n.bind(null,315)),"v-4f917bd3":()=>n.e(35).then(n.bind(null,316)),"v-87b4d6ae":()=>n.e(36).then(n.bind(null,317)),"v-7bafdcee":()=>n.e(37).then(n.bind(null,318)),"v-6abbdcee":()=>n.e(38).then(n.bind(null,319)),"v-ded899ca":()=>n.e(39).then(n.bind(null,320)),"v-09883f07":()=>n.e(40).then(n.bind(null,321)),"v-40b685e4":()=>n.e(41).then(n.bind(null,322)),"v-a971ed74":()=>n.e(42).then(n.bind(null,323))};function Qa(t){const e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}const Ja=/-(\w)/g,Za=Qa(t=>t.replace(Ja,(t,e)=>e?e.toUpperCase():"")),Xa=/\B([A-Z])/g,Ya=Qa(t=>t.replace(Xa,"-$1").toLowerCase()),ts=Qa(t=>t.charAt(0).toUpperCase()+t.slice(1));function es(t,e){if(!e)return;if(t(e))return t(e);return e.includes("-")?t(ts(Za(e))):t(ts(e))||t(Ya(e))}const ns=Object.assign({},Ga,Ka),rs=t=>ns[t],os=t=>Ka[t],is=t=>Ga[t],as=t=>Gn.component(t);function ss(t){return es(os,t)}function cs(t){return es(is,t)}function us(t){return es(rs,t)}function ls(t){return es(as,t)}function fs(...t){return Promise.all(t.filter(t=>t).map(async t=>{if(!ls(t)&&us(t)){const e=await us(t)();Gn.component(t,e.default)}}))}function ps(t,e){"undefined"!=typeof window&&window.__VUEPRESS__&&(window.__VUEPRESS__[t]=e)}var ds=n(86),hs=n.n(ds),vs=n(87),ms=n.n(vs),ys={created(){if(this.siteMeta=this.$site.headTags.filter(([t])=>"meta"===t).map(([t,e])=>e),this.$ssrContext){const e=this.getMergedMetaTags();this.$ssrContext.title=this.$title,this.$ssrContext.lang=this.$lang,this.$ssrContext.pageMeta=(t=e)?t.map(t=>{let e="{e+=` ${n}="${ms()(t[n])}"`}),e+">"}).join("\n "):"",this.$ssrContext.canonicalLink=bs(this.$canonicalUrl)}var t},mounted(){this.currentMetaTags=[...document.querySelectorAll("meta")],this.updateMeta(),this.updateCanonicalLink()},methods:{updateMeta(){document.title=this.$title,document.documentElement.lang=this.$lang;const t=this.getMergedMetaTags();this.currentMetaTags=_s(t,this.currentMetaTags)},getMergedMetaTags(){const t=this.$page.frontmatter.meta||[];return hs()([{name:"description",content:this.$description}],t,this.siteMeta,xs)},updateCanonicalLink(){gs(),this.$canonicalUrl&&document.head.insertAdjacentHTML("beforeend",bs(this.$canonicalUrl))}},watch:{$page(){this.updateMeta(),this.updateCanonicalLink()}},beforeDestroy(){_s(null,this.currentMetaTags),gs()}};function gs(){const t=document.querySelector("link[rel='canonical']");t&&t.remove()}function bs(t=""){return t?``:""}function _s(t,e){if(e&&[...e].filter(t=>t.parentNode===document.head).forEach(t=>document.head.removeChild(t)),t)return t.map(t=>{const e=document.createElement("meta");return Object.keys(t).forEach(n=>{e.setAttribute(n,t[n])}),document.head.appendChild(e),e})}function xs(t){for(const e of["name","property","itemprop"])if(t.hasOwnProperty(e))return t[e]+e;return JSON.stringify(t)}var ws=n(88),Os={mounted(){window.addEventListener("scroll",this.onScroll)},methods:{onScroll:n.n(ws)()((function(){this.setActiveHash()}),300),setActiveHash(){const t=[].slice.call(document.querySelectorAll(".sidebar-link")),e=[].slice.call(document.querySelectorAll(".header-anchor")).filter(e=>t.some(t=>t.hash===e.hash)),n=Math.max(window.pageYOffset,document.documentElement.scrollTop,document.body.scrollTop),r=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),o=window.innerHeight+n;for(let t=0;t=i.parentElement.offsetTop+10&&(!a||n{this.$nextTick(()=>{this.$vuepress.$set("disableScrollBehavior",!1)})})}}}},beforeDestroy(){window.removeEventListener("scroll",this.onScroll)}},Cs=n(22),$s=n.n(Cs),ks=[ys,Os,{mounted(){$s.a.configure({showSpinner:!1}),this.$router.beforeEach((t,e,n)=>{t.path===e.path||Gn.component(t.name)||$s.a.start(),n()}),this.$router.afterEach(()=>{$s.a.done(),this.isSidebarOpen=!1})}}],Ss={name:"GlobalLayout",computed:{layout(){const t=this.getLayout();return ps("layout",t),Gn.component(t)}},methods:{getLayout(){if(this.$page.path){const t=this.$page.frontmatter.layout;return t&&(this.$vuepress.getLayoutAsyncComponent(t)||this.$vuepress.getVueComponent(t))?t:"Layout"}return"NotFound"}}},js=n(14),Es=Object(js.a)(Ss,(function(){return(0,this._self._c)(this.layout,{tag:"component"})}),[],!1,null,null,null).exports;!function(t,e,n){switch(e){case"components":t[e]||(t[e]={}),Object.assign(t[e],n);break;case"mixins":t[e]||(t[e]=[]),t[e].push(...n);break;default:throw new Error("Unknown option name.")}}(Es,"mixins",ks);const Ps=[{name:"v-3c88bbf2",path:"/",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-3c88bbf2").then(n)}},{path:"/index.html",redirect:"/"},{name:"v-0decf914",path:"/about/",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-0decf914").then(n)}},{path:"/about/index.html",redirect:"/about/"},{name:"v-d7e5bcfc",path:"/docs/",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-d7e5bcfc").then(n)}},{path:"/docs/index.html",redirect:"/docs/"},{name:"v-c864372e",path:"/docs/adapters.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-c864372e").then(n)}},{name:"v-102beaee",path:"/docs/client-codegen.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-102beaee").then(n)}},{name:"v-23f0ba6e",path:"/docs/client.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-23f0ba6e").then(n)}},{name:"v-4419f5c9",path:"/docs/examples.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-4419f5c9").then(n)}},{name:"v-05e5796e",path:"/docs/federation.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-05e5796e").then(n)}},{name:"v-6d148503",path:"/docs/interop.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-6d148503").then(n)}},{name:"v-41c3bc69",path:"/docs/laminext.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-41c3bc69").then(n)}},{name:"v-2bf9c0ae",path:"/docs/middleware.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-2bf9c0ae").then(n)}},{name:"v-1c00b5c9",path:"/docs/optimization.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-1c00b5c9").then(n)}},{name:"v-56e4d50b",path:"/docs/relay-connections.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-56e4d50b").then(n)}},{name:"v-4f917bd3",path:"/docs/schema-comparison.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-4f917bd3").then(n)}},{name:"v-87b4d6ae",path:"/docs/schema-reporting.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-87b4d6ae").then(n)}},{name:"v-7bafdcee",path:"/docs/schema.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-7bafdcee").then(n)}},{name:"v-6abbdcee",path:"/docs/server-codegen.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-6abbdcee").then(n)}},{name:"v-ded899ca",path:"/docs/stitching.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-ded899ca").then(n)}},{name:"v-09883f07",path:"/docs/tools.html",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-09883f07").then(n)}},{name:"v-40b685e4",path:"/faq/",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-40b685e4").then(n)}},{path:"/faq/index.html",redirect:"/faq/"},{name:"v-a971ed74",path:"/resources/",component:Es,beforeEnter:(t,e,n)=>{fs("Layout","v-a971ed74").then(n)}},{path:"/resources/index.html",redirect:"/resources/"},{path:"*",component:Es}],As={title:"",description:"",base:"/caliban/",headTags:[["link",{rel:"icon",href:"/caliban/caliban.png"}]],pages:[{title:"Home",frontmatter:{home:!0,heroImage:"/caliban.svg",actionText:"Get Started →",actionLink:"/docs/",features:[{title:"High performance",details:"While all public interfaces are pure and immutable, the library's internals are optimized for speed."},{title:"Minimal boilerplate",details:"No need to manually define schemas for every type in your API. Let the compiler handle the tedious work."},{title:"Excellent interoperability",details:"Out-of-the-box support for major HTTP server libraries, effect types, JSON libraries, and more."}]},regularPath:"/",relativePath:"README.md",key:"v-3c88bbf2",path:"/"},{title:"About",frontmatter:{},regularPath:"/about/",relativePath:"about/README.md",key:"v-0decf914",path:"/about/"},{title:"Getting Started",frontmatter:{},regularPath:"/docs/",relativePath:"docs/README.md",key:"v-d7e5bcfc",path:"/docs/",headers:[{level:2,title:"A simple schema",slug:"a-simple-schema"},{level:2,title:"Serving over HTTP",slug:"serving-over-http"},{level:2,title:"Interop with 3rd-party libraries",slug:"interop-with-3rd-party-libraries"}]},{title:"Http Adapters",frontmatter:{},regularPath:"/docs/adapters.html",relativePath:"docs/adapters.md",key:"v-c864372e",path:"/docs/adapters.html",headers:[{level:2,title:"Built-in tapir adapters",slug:"built-in-tapir-adapters"},{level:2,title:"Json handling",slug:"json-handling"},{level:2,title:"Make your own adapter",slug:"make-your-own-adapter"},{level:2,title:"High-performance QuickAdapter",slug:"high-performance-quickadapter"},{level:3,title:"Usage",slug:"usage"},{level:3,title:"Customization",slug:"customization"}]},{title:"Code Generation",frontmatter:{},regularPath:"/docs/client-codegen.html",relativePath:"docs/client-codegen.md",key:"v-102beaee",path:"/docs/client-codegen.html",headers:[{level:2,title:"CalibanPlugin",slug:"calibanplugin"},{level:3,title:"From a schema file",slug:"from-a-schema-file"},{level:3,title:"From a server URL",slug:"from-a-server-url"},{level:3,title:"Generation settings",slug:"generation-settings"},{level:3,title:"Manual generation",slug:"manual-generation"},{level:2,title:"CompileTimeCalibanPlugin",slug:"compiletimecalibanplugin"},{level:3,title:"Server side configuration",slug:"server-side-configuration"},{level:3,title:"Client side configuration",slug:"client-side-configuration"},{level:3,title:"Additional information about CompileTimeCalibanPlugin",slug:"additional-information-about-compiletimecalibanplugin"}]},{title:"Getting Started",frontmatter:{},regularPath:"/docs/client.html",relativePath:"docs/client.md",key:"v-23f0ba6e",path:"/docs/client.html",headers:[{level:2,title:"Dependencies",slug:"dependencies"},{level:2,title:"Code generation",slug:"code-generation"},{level:2,title:"Query building",slug:"query-building"},{level:2,title:"Request execution",slug:"request-execution"}]},{title:"Examples",frontmatter:{},regularPath:"/docs/examples.html",relativePath:"docs/examples.md",key:"v-4419f5c9",path:"/docs/examples.html"},{title:"Federation",frontmatter:{},regularPath:"/docs/federation.html",relativePath:"docs/federation.md",key:"v-05e5796e",path:"/docs/federation.html",headers:[{level:2,title:"Dependencies",slug:"dependencies"},{level:2,title:"Federating",slug:"federating"},{level:2,title:"Tracing",slug:"tracing"},{level:2,title:"Federation V2",slug:"federation-v2"},{level:3,title:"Customizing Federation",slug:"customizing-federation"}]},{title:"Interop with other libraries",frontmatter:{},regularPath:"/docs/interop.html",relativePath:"docs/interop.md",key:"v-6d148503",path:"/docs/interop.html",headers:[{level:2,title:"Cats Effect",slug:"cats-effect"},{level:2,title:"Monix (only with cats-effect 2.x)",slug:"monix-only-with-cats-effect-2-x"},{level:2,title:"Tapir",slug:"tapir"},{level:3,title:"GraphQL restrictions",slug:"graphql-restrictions"}]},{title:"Laminext Integration",frontmatter:{},regularPath:"/docs/laminext.html",relativePath:"docs/laminext.md",key:"v-41c3bc69",path:"/docs/laminext.html"},{title:"Middleware",frontmatter:{},regularPath:"/docs/middleware.html",relativePath:"docs/middleware.md",key:"v-2bf9c0ae",path:"/docs/middleware.html",headers:[{level:2,title:"Wrapper types",slug:"wrapper-types"},{level:2,title:"Pre-defined wrappers",slug:"pre-defined-wrappers"},{level:2,title:"Wrapping the interpreter",slug:"wrapping-the-interpreter"},{level:2,title:"Customizing error responses",slug:"customizing-error-responses"},{level:2,title:"Wrapping the GraphQL",slug:"wrapping-the-graphql"},{level:2,title:"Cost Estimation",slug:"cost-estimation"},{level:2,title:"OpenTelemetry Tracing",slug:"opentelemetry-tracing"}]},{title:"Query optimization",frontmatter:{},regularPath:"/docs/optimization.html",relativePath:"docs/optimization.md",key:"v-1c00b5c9",path:"/docs/optimization.html",headers:[{level:2,title:"Introducing ZQuery",slug:"introducing-zquery"},{level:2,title:"Building a DataSource",slug:"building-a-datasource"},{level:2,title:"ZQuery constructors and operators",slug:"zquery-constructors-and-operators"},{level:2,title:"Using ZQuery with Caliban",slug:"using-zquery-with-caliban"},{level:2,title:"Using field metadata",slug:"using-field-metadata"},{level:2,title:"@defer support (experimental)",slug:"defer-support-experimental"},{level:3,title:"Usage",slug:"usage"}]},{title:"Relay Connections",frontmatter:{},regularPath:"/docs/relay-connections.html",relativePath:"docs/relay-connections.md",key:"v-56e4d50b",path:"/docs/relay-connections.html",headers:[{level:2,title:"Cursors",slug:"cursors"}]},{title:"Schema comparison",frontmatter:{},regularPath:"/docs/schema-comparison.html",relativePath:"docs/schema-comparison.md",key:"v-4f917bd3",path:"/docs/schema-comparison.html"},{title:"Schema Reporting",frontmatter:{},regularPath:"/docs/schema-reporting.html",relativePath:"docs/schema-reporting.md",key:"v-87b4d6ae",path:"/docs/schema-reporting.html"},{title:"Schema generation",frontmatter:{},regularPath:"/docs/schema.html",relativePath:"docs/schema.md",key:"v-7bafdcee",path:"/docs/schema.html",headers:[{level:2,title:"Enums, unions, interfaces",slug:"enums-unions-interfaces"},{level:2,title:"Case classes and sealed traits",slug:"case-classes-and-sealed-traits"},{level:3,title:"Auto derivation",slug:"auto-derivation"},{level:3,title:"Semi-auto derivation",slug:"semi-auto-derivation"},{level:3,title:"Combining auto and semi-auto derivation",slug:"combining-auto-and-semi-auto-derivation"},{level:3,title:"Deriving fields from case class methods (Scala 3 only)",slug:"deriving-fields-from-case-class-methods-scala-3-only"},{level:2,title:"Arguments",slug:"arguments"},{level:2,title:"Custom types",slug:"custom-types"},{level:2,title:"Effects",slug:"effects"},{level:2,title:"Annotations",slug:"annotations"},{level:2,title:"Java 8 Time types",slug:"java-8-time-types"},{level:2,title:"Building Schemas by hand",slug:"building-schemas-by-hand"}]},{title:"Code generation",frontmatter:{},regularPath:"/docs/server-codegen.html",relativePath:"docs/server-codegen.md",key:"v-6abbdcee",path:"/docs/server-codegen.html",headers:[{level:2,title:"Options",slug:"options"},{level:2,title:"Lazy evaluation",slug:"lazy-evaluation"},{level:2,title:"Newtype declaration",slug:"newtype-declaration"}]},{title:"Stitching",frontmatter:{},regularPath:"/docs/stitching.html",relativePath:"docs/stitching.md",key:"v-ded899ca",path:"/docs/stitching.html",headers:[{level:2,title:"Dependencies",slug:"dependencies"},{level:2,title:"Stitching in Action",slug:"stitching-in-action"},{level:2,title:"Things not yet supported",slug:"things-not-yet-supported"}]},{title:"Getting Started",frontmatter:{},regularPath:"/docs/tools.html",relativePath:"docs/tools.md",key:"v-09883f07",path:"/docs/tools.html",headers:[{level:2,title:"Dependency",slug:"dependency"}]},{title:"FAQ",frontmatter:{},regularPath:"/faq/",relativePath:"faq/README.md",key:"v-40b685e4",path:"/faq/",headers:[{level:3,title:"I don't know where to start 😥",slug:"i-don-t-know-where-to-start-😥"},{level:3,title:"I'm getting a compilation error saying a Schema is missing, but I don't know which one.",slug:"i-m-getting-a-compilation-error-saying-a-schema-is-missing-but-i-don-t-know-which-one"},{level:3,title:"I want to use Caliban, but I use Cats Effect / Monix instead of ZIO.",slug:"i-want-to-use-caliban-but-i-use-cats-effect-monix-instead-of-zio"},{level:3,title:'My query fails with an "Effect failure" error. How can I get more details?',slug:"my-query-fails-with-an-effect-failure-error-how-can-i-get-more-details"},{level:3,title:"I have more than 22 fields in my Query, I can't create a case class for it.",slug:"i-have-more-than-22-fields-in-my-query-i-can-t-create-a-case-class-for-it"},{level:3,title:"How to deal with authentication/authorization?",slug:"how-to-deal-with-authentication-authorization"},{level:3,title:"I have 2 case classes with the same name (different packages). How to avoid conflicts?",slug:"i-have-2-case-classes-with-the-same-name-different-packages-how-to-avoid-conflicts"},{level:3,title:"The auto-generated schema shows a field is nullable, but I want it non-nullable instead.",slug:"the-auto-generated-schema-shows-a-field-is-nullable-but-i-want-it-non-nullable-instead"},{level:3,title:"Can I use a union as input?",slug:"can-i-use-a-union-as-input"},{level:3,title:"How to deal with recursive types?",slug:"how-to-deal-with-recursive-types"},{level:3,title:'I\'m getting a "Method too large" compiler error.',slug:"i-m-getting-a-method-too-large-compiler-error"},{level:3,title:"How can I define a Schema for a Java enum?",slug:"how-can-i-define-a-schema-for-a-java-enum"},{level:3,title:"I don't want to use Throwable as my error type",slug:"i-don-t-want-to-use-throwable-as-my-error-type"},{level:3,title:"My interface is missing from the schema",slug:"my-interface-is-missing-from-the-schema"},{level:3,title:"Can I check that a GraphQL query is valid at compile-time?",slug:"can-i-check-that-a-graphql-query-is-valid-at-compile-time"}]},{title:"Resources",frontmatter:{},regularPath:"/resources/",relativePath:"resources/README.md",key:"v-a971ed74",path:"/resources/",headers:[{level:2,title:"Talks",slug:"talks"},{level:2,title:"Blog Articles",slug:"blog-articles"},{level:2,title:"Related Projects",slug:"related-projects"}]}],themeConfig:{logo:"/caliban.svg",locales:{"/":{selectText:"Language",label:"English",nav:[{text:"Documentation",link:"/docs/"},{text:"Resources",link:"/resources/"},{text:"FAQ",link:"/faq/"},{text:"About",link:"/about/"},{text:"Github",link:"https://github.com/ghostdogpr/caliban"},{text:"Scaladoc",link:"https://javadoc.io/doc/com.github.ghostdogpr/caliban_3/"}],sidebar:{"/docs/":[{title:"Caliban Server",collapsable:!0,sidebarDepth:2,children:["","schema","server-codegen","adapters","middleware","optimization","interop","federation","relay-connections","schema-reporting"]},{title:"Caliban Client",collapsable:!0,sidebarDepth:2,children:["client","client-codegen","laminext"]},{title:"Caliban Tools",collapsable:!0,sidebarDepth:2,children:["tools","stitching","schema-comparison"]},{title:"Examples",path:"examples"}]}}}},locales:{"/":{lang:"en-US",title:"Caliban",description:"Functional GraphQL library for Scala",path:"/"}}};n(234);Gn.component("Badge",()=>Promise.all([n.e(0),n.e(4)]).then(n.bind(null,302))),Gn.component("CodeBlock",()=>Promise.all([n.e(0),n.e(5)]).then(n.bind(null,298))),Gn.component("CodeGroup",()=>Promise.all([n.e(0),n.e(6)]).then(n.bind(null,299)));n(235);var Ts=[{},({Vue:t})=>{t.mixin({computed:{$dataBlock(){return this.$options.__data__block__}}})},{},{}],Ls=[];class Rs extends class{constructor(){this.store=new Gn({data:{state:{}}})}$get(t){return this.store.state[t]}$set(t,e){Gn.set(this.store.state,t,e)}$emit(...t){this.store.$emit(...t)}$on(...t){this.store.$on(...t)}}{}Object.assign(Rs.prototype,{getPageAsyncComponent:ss,getLayoutAsyncComponent:cs,getAsyncComponent:us,getVueComponent:ls});var Is={install(t){const e=new Rs;t.$vuepress=e,t.prototype.$vuepress=e}};function Ms(t,e){const n=e.toLowerCase();return t.options.routes.some(t=>t.path.toLowerCase()===n)}var Ds={props:{pageKey:String,slotKey:{type:String,default:"default"}},render(t){const e=this.pageKey||this.$parent.$page.key;return ps("pageKey",e),Gn.component(e)||Gn.component(e,ss(e)),Gn.component(e)?t(e):t("")}},Ns={functional:!0,props:{slotKey:String,required:!0},render:(t,{props:e,slots:n})=>t("div",{class:["content__"+e.slotKey]},n()[e.slotKey])},zs={computed:{openInNewWindowTitle(){return this.$themeLocaleConfig.openNewWindowText||"(opens new window)"}}},Fs=(n(236),n(237),Object(js.a)(zs,(function(){var t=this._self._c;return t("span",[t("svg",{staticClass:"icon outbound",attrs:{xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",x:"0px",y:"0px",viewBox:"0 0 100 100",width:"15",height:"15"}},[t("path",{attrs:{fill:"currentColor",d:"M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"}}),this._v(" "),t("polygon",{attrs:{fill:"currentColor",points:"45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"}})]),this._v(" "),t("span",{staticClass:"sr-only"},[this._v(this._s(this.openInNewWindowTitle))])])}),[],!1,null,null,null).exports),Us={functional:!0,render(t,{parent:e,children:n}){if(e._isMounted)return n;e.$once("hook:mounted",()=>{e.$forceUpdate()})}};Gn.config.productionTip=!1,Gn.use(Ha),Gn.use(Is),Gn.mixin(function(t,e,n=Gn){!function(t){t.locales&&Object.keys(t.locales).forEach(e=>{t.locales[e].path=e});Object.freeze(t)}(e),n.$vuepress.$set("siteData",e);const r=new(t(n.$vuepress.$get("siteData"))),o=Object.getOwnPropertyDescriptors(Object.getPrototypeOf(r)),i={};return Object.keys(o).reduce((t,e)=>(e.startsWith("$")&&(t[e]=o[e].get),t),i),{computed:i}}(t=>class{setPage(t){this.__page=t}get $site(){return t}get $themeConfig(){return this.$site.themeConfig}get $frontmatter(){return this.$page.frontmatter}get $localeConfig(){const{locales:t={}}=this.$site;let e,n;for(const r in t)"/"===r?n=t[r]:0===this.$page.path.indexOf(r)&&(e=t[r]);return e||n||{}}get $siteTitle(){return this.$localeConfig.title||this.$site.title||""}get $canonicalUrl(){const{canonicalUrl:t}=this.$page.frontmatter;return"string"==typeof t&&t}get $title(){const t=this.$page,{metaTitle:e}=this.$page.frontmatter;if("string"==typeof e)return e;const n=this.$siteTitle,r=t.frontmatter.home?null:t.frontmatter.title||t.title;return n?r?r+" | "+n:n:r||"VuePress"}get $description(){const t=function(t){if(t){const e=t.filter(t=>"description"===t.name)[0];if(e)return e.content}}(this.$page.frontmatter.meta);return t||(this.$page.frontmatter.description||this.$localeConfig.description||this.$site.description||"")}get $lang(){return this.$page.frontmatter.lang||this.$localeConfig.lang||"en-US"}get $localePath(){return this.$localeConfig.path||"/"}get $themeLocaleConfig(){return(this.$site.themeConfig.locales||{})[this.$localePath]||{}}get $page(){return this.__page?this.__page:function(t,e){for(let n=0;nn||(t.hash?!Gn.$vuepress.$get("disableScrollBehavior")&&{selector:decodeURIComponent(t.hash)}:{x:0,y:0})});!function(t){t.beforeEach((e,n,r)=>{if(Ms(t,e.path))r();else if(/(\/|\.html)$/.test(e.path))if(/\/$/.test(e.path)){const n=e.path.replace(/\/$/,"")+".html";Ms(t,n)?r(n):r()}else r();else{const n=e.path+"/",o=e.path+".html";Ms(t,o)?r(o):Ms(t,n)?r(n):r()}})}(n);const r={};try{await Promise.all(Ts.filter(t=>"function"==typeof t).map(e=>e({Vue:Gn,options:r,router:n,siteData:As,isServer:t})))}catch(t){console.error(t)}return{app:new Gn(Object.assign(r,{router:n,render:t=>t("div",{attrs:{id:"app"}},[t("RouterView",{ref:"layout"}),t("div",{class:"global-ui"},Ls.map(e=>t(e)))])})),router:n}}(!1).then(({app:t,router:e})=>{e.onReady(()=>{t.$mount("#app")})})}]); \ No newline at end of file diff --git a/docs/docs/adapters.html b/docs/docs/adapters.html index d815dae940..2dddd605e8 100644 --- a/docs/docs/adapters.html +++ b/docs/docs/adapters.html @@ -8,7 +8,7 @@ - + @@ -22,7 +22,7 @@ About

# Http Adapters

Once you have an interpreter able to execute GraphQL queries, you usually want to expose it using an HTTP API. + (opens new window)

# Http Adapters

Once you have an interpreter able to execute GraphQL queries, you usually want to expose it using an HTTP API. Caliban comes with a few "ready-to-use" components (called "adapters") to expose your API with the most popular HTTP libraries.

`QuickAdapter`

Starting with v2.4.3, Caliban provides the opinionated QuickAdapter -that favours ease-of-use and performance at the expense of customizability.

If you want the best possible performance, make sure to check it out!

# Built-in tapir adapters

Under the hood, adapters use the tapir (opens new window) library, so you can easily create a custom adapter with anything that tapir supports.

The following adapters are provided:

  • Http4sAdapter exposes a route for http4s.
  • ZHttpAdapter exposes a route for zio-http. This one doesn't support uploads yet.
  • PlayHttpAdapter exposes a route for play.
  • AkkaHttpAdapter exposes a route for akka.
  • PekkoHttpAdapter exposes a route for pekko.

To use them, you first need to transform your GraphQLInterpreter into a new type of interpreter that supports the protocol you want to use. +that favours ease-of-use and performance at the expense of customizability.

If you want the best possible performance, make sure to check it out!

# Built-in tapir adapters

Under the hood, adapters use the tapir (opens new window) library, so you can easily create a custom adapter with anything that tapir supports.

The following adapters are provided:

  • Http4sAdapter exposes a route for http4s.
  • QuickAdapter exposes a route for zio-http.
  • PlayHttpAdapter exposes a route for play.
  • AkkaHttpAdapter exposes a route for akka.
  • PekkoHttpAdapter exposes a route for pekko.

To use them, you first need to transform your GraphQLInterpreter obtained from api.interpreter into a new type of interpreter that supports the protocol you want to use. There are 3 of them:

These interpreters expose 2 powerful methods:

  • configure takes a Configurator[R] which is an alias for URIO[R & Scope, Unit]. It allows configuring the interpreter by running an effect that will run for each request and that can modify the configuration of the running fiber. Built-in configurators such as Configurator.setSkipValidation, Configurator.setEnableIntrospection and Configurator.setQueryExecution let you dynamically change the configuration of the interpreter.
  • intercept takes an Interceptor[-R1, +R] which is an alias for ZLayer[R1 & ServerRequest, TapirResponse, R]. It is basically a more powerful version of configure that gives you access to the incoming request (ServerRequest) and lets you modify the environment of the interpreter (from R to R1). A typical use case would be to extract an authentication token from the request and eliminate the authentication requirement from the environment if the token is valid. See an example here (opens new window).

In addition to that, the WebSocketInterpreter constructor comes with 2 optional parameters:

  • keepAliveInterval (default: empty) defines the interval for the server to send keep alive messages to the client
  • webSocketHooks (default: empty) gives you some hooks around the WebSocket lifecycle (useful for authentication)

Once your interpreter is correctly configured, you can use one of these 3 functions exposed by each built-in adapter:

  • makeHttpService turns an HttpInterpreter into a route for the corresponding library
  • makeHttpUploadService turns an HttpUploadInterpreter into a route for the corresponding library
  • makeWebSocketService turns a WebSocketInterpreter into a route for the corresponding library
val graphQLInterpreter: GraphQLInterpreter[AuthToken, CalibanError] = ???
@@ -76,11 +76,11 @@
 
 val api: GraphQL[Any] = ???
 
-api.runServer(
+api.unsafe.runServer(
   port = 8080,
   apiPath = "/api/graphql",
   graphiqlPath = Some("/graphiql"),
-  uploadPath = Some("/upload/graphql"), // Optional, for enabling GraphQL uploads
+  uploadPath = Some("/upload/graphql"), // optional, for enabling GraphQL uploads
 )
 

Alternatively, you can also create a zio-http Handler and manually compose it into an app:

import caliban._
 import caliban.quick._
@@ -105,13 +105,13 @@
 

# Customization

The QuickAdapter exposes the following methods that allow you to customize the server or apply middleware to the routes:

  • configure which takes a Configurator[R] similar to the tapir-based adapters
  • handlers which returns a QuickHandlers[R] which contains individual handlers to manually construct routes. Note that this handler is only for the api routes. To construct the graphiql handler use caliban.GraphiQLHandler.handler.

For more info on customization and middleware, check out the adapter examples (opens new window)!

- + diff --git a/docs/docs/client-codegen.html b/docs/docs/client-codegen.html index d721679cdd..033f8e5558 100644 --- a/docs/docs/client-codegen.html +++ b/docs/docs/client-codegen.html @@ -8,7 +8,7 @@ - + @@ -22,7 +22,7 @@ About

# Code Generation

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

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

The second one, named CompileTimeCalibanPlugin, allows you to generate the client code from your server code. This second "meta" plugin is actually made of two "concrete" plugins, CompileTimeCalibanServerPlugin and CompileTimeCalibanClientPlugin, that you'll @@ -140,6 +140,6 @@ →

- + diff --git a/docs/docs/client.html b/docs/docs/client.html index 4be9370d3e..957060ded5 100644 --- a/docs/docs/client.html +++ b/docs/docs/client.html @@ -8,7 +8,7 @@ - + @@ -22,7 +22,7 @@ About

# Getting Started

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

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

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

# Dependencies

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

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

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

"com.github.ghostdogpr" %%% "caliban-client" % "2.6.0"
@@ -94,13 +94,13 @@
 

As a result, we get a ZIO Task whose return type is the same as our SelectionBuilder. The sttp request does not only contain the request to send, but also takes care of parsing the response into the expected type.

The examples (opens new window) project contains a runnable sample code that queries the example GraphQL backend.

Limitations

Only Queries and Mutations are supported as sttp requests. Subscriptions 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).

Type extensions are not supported by the codegen tool.

- + diff --git a/docs/docs/examples.html b/docs/docs/examples.html index 7020db336e..054c81ae30 100644 --- a/docs/docs/examples.html +++ b/docs/docs/examples.html @@ -8,7 +8,7 @@ - + @@ -22,7 +22,7 @@ About
- + diff --git a/docs/docs/federation.html b/docs/docs/federation.html index fe199f79b9..068d06fae2 100644 --- a/docs/docs/federation.html +++ b/docs/docs/federation.html @@ -8,7 +8,7 @@ - + @@ -22,7 +22,7 @@ About

# Federation

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

# Dependencies

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

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

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

# Federation

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

# Dependencies

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

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

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

# Federating

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

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

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

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

import caliban.federation.v1._
@@ -99,12 +99,12 @@
 
- + diff --git a/docs/docs/index.html b/docs/docs/index.html index 5781f730b4..a6ae7c4c63 100644 --- a/docs/docs/index.html +++ b/docs/docs/index.html @@ -8,7 +8,7 @@ - + @@ -22,7 +22,7 @@ About

# Getting Started

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

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

The design principles of Caliban are the following:

# A simple example

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

"com.github.ghostdogpr" %% "caliban" % "2.6.0"
-

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.

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

case class Character(name: String, age: Int)
+   (opens new window)

# Getting Started

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

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

The design principles of Caliban are the following:

# A simple schema

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

"com.github.ghostdogpr" %% "caliban" % "2.6.0"
+

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

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

case class Character(name: String, age: Int)
 
 def getCharacters: List[Character] = Nil
 def getCharacter(name: String): Option[Character] = ???
-

Let's create a case class named Queries that will represent our API, with 2 fields named and modeled after the functions we want to expose (a record of functions). We then create a value of this class that calls our actual functions. This is our resolver.

// schema
+

Let's create a case class named Queries that will represent our API, with 2 fields named and modeled after the functions we want to expose. +We then create a value of this class that calls our actual functions. This is our resolver.

// schema
 case class CharacterName(name: String)
 case class Queries(characters: List[Character],
                    character: CharacterName => Option[Character])
 // resolver
 val queries = Queries(getCharacters, args => getCharacter(args.name))
-

The next step is creating our GraphQL API definition. First, we wrap our query resolver inside a RootResolver, the root object that contains queries, mutations and subscriptions. Only queries are mandatory. -Then we can call the graphQL function which will turn our simple resolver value into a GraphQL API definition. +

The next step is creating our GraphQL API definition.

First, we wrap our query resolver inside a RootResolver, the root object that contains queries, mutations and subscriptions. Only queries are mandatory. +Then we call the graphQL function which will turn our simple resolver value into a GraphQL API definition. The whole schema will be derived at compile time, meaning that if it compiles, it will be able to serve it.

import caliban._
 import caliban.schema.Schema.auto._
 import caliban.schema.ArgBuilder.auto._
@@ -63,72 +65,39 @@
   characters: [Character!]!
   character(name: String!): Character
 }
-

In order to process requests, you need to turn your API into an interpreter, which can be done easily by calling .interpreter. -An interpreter is a light wrapper around the API definition that allows plugging in some middleware and possibly modifying the environment and error types (see Middleware for more info). -Creating the interpreter may fail with a ValidationError if some type is found invalid.

for {
-  interpreter <- api.interpreter
-} yield interpreter
-

Now you can call interpreter.execute with a given GraphQL query, and you will get an ZIO[R, Nothing, GraphQLResponse[CalibanError]] as a response, with GraphQLResponse defined as follows:

case class GraphQLResponse[+E](data: ResponseValue, errors: List[E])
-

Use ResponseValue#toString to get the JSON representation of the result.

val query = """
-  {
-    characters {
-      name
-    }
-  }"""
+

# Serving over HTTP

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

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

"com.github.ghostdogpr" %% "caliban-quick"  % "2.6.0"
+

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

import caliban.quick._ // adds extension methods to `api`
 
-for {
-  interpreter <- api.interpreter
-  result      <- interpreter.execute(query)
-  _           <- zio.ZIO.debug(result.data.toString)
-} yield ()
-

A CalibanError can be:

  • a ParsingError: the query has invalid syntax
  • a ValidationError: the query was parsed but does not match the schema
  • an ExecutionError: an error happened while executing the query

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 caliban-http4s (opens new window) module provides an Http4sAdapter that exposes an interpreter over HTTP and WebSocket using http4s. There are also similar adapters for Akka HTTP, Pekko HTTP, Play and zio-http. -Read more on the adapters' documentation.

Combining GraphQL APIs

You don't have to define all your root fields into a single case class: you can use smaller case classes and combine GraphQL objects using the |+| operator.

val api1 = graphQL(...)
-val api2 = graphQL(...)
-
-val api = api1 |+| api2
-

You can use .rename to change the names of the generated root types.

# Mutations

Creating mutations is the same as queries, except you pass them as the second argument to RootResolver:

import zio.Task
-
-case class CharacterArgs(name: String)
-case class Mutations(deleteCharacter: CharacterArgs => Task[Boolean])
-val mutations = Mutations(_ => ???)
-val api = graphQL(RootResolver(queries, mutations))
-

# Subscriptions

Similarly, subscriptions are passed as the third argument to RootResolver:

import zio.stream.ZStream
-
-case class Subscriptions(deletedCharacter: ZStream[Any, Nothing, Character])
-val subscriptions = Subscriptions(???)
-val api = graphQL(RootResolver(queries, mutations, subscriptions))
-

All the fields of the subscription root case class MUST return ZStream or ? => ZStream objects. When a subscription request is received, an output stream of ResponseValue (a StreamValue) will be returned wrapped inside an ObjectValue.

# Serving over HTTP

The easiest (and most performant!) way to expose your API over HTTP is to use the optional caliban-quick module:

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

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

import caliban._
-import caliban.quick._ // Adds syntax to `GraphQL`
-
-api.runServer(
+api.unsafe.runServer(
   port = 8080,
   apiPath = "/api/graphql",
-  graphiqlPath = Some("/graphiql")
 )
 

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

# Interop with 3rd-party libraries

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

"com.github.ghostdogpr" %% "caliban-http4s"     % "2.6.0" // routes for http4s
 "com.github.ghostdogpr" %% "caliban-akka-http"  % "2.6.0" // routes for akka-http
+"com.github.ghostdogpr" %% "caliban-pekko-http" % "2.6.0" // routes for pekko-http
 "com.github.ghostdogpr" %% "caliban-play"       % "2.6.0" // routes for play
-"com.github.ghostdogpr" %% "caliban-zio-http"   % "2.6.0" // routes for zio-http
-"com.github.ghostdogpr" %% "caliban-cats"       % "2.6.0" // interop with cats effect
+
+"com.github.ghostdogpr" %% "caliban-cats"       % "2.6.0" // interop with cats-effect
 "com.github.ghostdogpr" %% "caliban-monix"      % "2.6.0" // interop with monix
 "com.github.ghostdogpr" %% "caliban-tapir"      % "2.6.0" // interop with tapir
-"com.github.ghostdogpr" %% "caliban-federation" % "2.6.0" // interop with apollo federation
-"com.github.ghostdogpr" %% "caliban-tracing"    % "2.6.0" // interop with zio-telemetry
-

Support for JSON encoding / decoding of the inputs and responses for tapir-based adapters is enabled by adding one of the following dependencies to your build.sbt file:

"com.softwaremill.sttp.tapir" %% "tapir-json-circe"     % "1.2.11" // Circe
-"com.softwaremill.sttp.tapir" %% "tapir-jsoniter-scala" % "1.2.11" // Jsoniter
-"com.softwaremill.sttp.tapir" %% "tapir-json-play"      % "1.2.11" // Play JSON
-"com.softwaremill.sttp.tapir" %% "tapir-json-zio"       % "1.2.11" // ZIO JSON
+
+"com.github.ghostdogpr" %% "caliban-federation" % "2.6.0" // apollo federation
+"com.github.ghostdogpr" %% "caliban-reporting"  % "2.6.0" // apollo schema reporting
+"com.github.ghostdogpr" %% "caliban-tracing"    % "2.6.0" // open-telemetry
+

Support for JSON encoding / decoding of the inputs and responses for tapir-based adapters is enabled by adding one of the following dependencies to your build.sbt file:

"com.softwaremill.sttp.tapir" %% "tapir-json-circe"     % "1.2.11" // circe
+"com.softwaremill.sttp.tapir" %% "tapir-jsoniter-scala" % "1.2.11" // jsoniter
+"com.softwaremill.sttp.tapir" %% "tapir-json-play"      % "1.2.11" // play-json
+"com.softwaremill.sttp.tapir" %% "tapir-json-zio"       % "1.2.11" // zio-json
 

And then later in your code (you only need one!):

import sttp.tapir.json.circe._
 import sttp.tapir.json.jsoniter._
 import sttp.tapir.json.play._
 import sttp.tapir.json.zio._
 

For more info on the adapters and the JSON implementations, see here.

- + diff --git a/docs/docs/interop.html b/docs/docs/interop.html index 5de4251255..10d20011a9 100644 --- a/docs/docs/interop.html +++ b/docs/docs/interop.html @@ -3,12 +3,12 @@ - Interop | Caliban + Interop with other libraries | Caliban - + @@ -22,7 +22,7 @@ About

# Interop

If you prefer using Cats Effect (opens new window) or Monix (opens new window) rather than ZIO, you can use the respective caliban-cats and caliban-monix modules.

The caliban-tapir module allows converting your Tapir (opens new window) endpoints into a GraphQL API.

# Cats Effect

You first need to import caliban.interop.cats.implicits._ and have an implicit zio.Runtime in scope. Then a few helpers are available:

  • the GraphQL object is enriched with interpreterAsync, a variant of interpreter that return an F[_]: Async instead of a ZIO.
  • the GraphQLInterpreter object is enriched with executeAsync and checkAsync, variants of execute and check that return an F[_]: Async instead of a ZIO.
  • the Http4sAdapter also has a helper to turn endpoints into cats-effect named convertHttpEndpointToF.

In addition to that, a Schema for any F[_]: Async: Dispatcher is provided. That means you can include fields with results wrapped in F in your queries, mutations or subscriptions.

There are two type classes responsible for the conversion between effects: caliban.interop.cats.ToEffect and caliban.interop.cats.FromEffect. + (opens new window)

# Interop with other libraries

If you prefer using Cats Effect (opens new window) or Monix (opens new window) rather than ZIO, you can use the respective caliban-cats and caliban-monix modules.

The caliban-tapir module allows converting your Tapir (opens new window) endpoints into a GraphQL API.

# Cats Effect

You first need to import caliban.interop.cats.implicits._ and have an implicit zio.Runtime in scope. Then a few helpers are available:

  • the GraphQL object is enriched with interpreterAsync, a variant of interpreter that return an F[_]: Async instead of a ZIO.
  • the GraphQLInterpreter object is enriched with executeAsync and checkAsync, variants of execute and check that return an F[_]: Async instead of a ZIO.
  • the Http4sAdapter also has a helper to turn endpoints into cats-effect named convertHttpEndpointToF.

In addition to that, a Schema for any F[_]: Async: Dispatcher is provided. That means you can include fields with results wrapped in F in your queries, mutations or subscriptions.

There are two type classes responsible for the conversion between effects: caliban.interop.cats.ToEffect and caliban.interop.cats.FromEffect. The instances are derived implicitly when Async[F], Dispatcher[F], and Runtime[R] are available in the implicit scope.

# Interop with cats.effect.IO

The following example shows how to create an interpreter and run a query while only using Cats IO.

import caliban._
 import caliban.interop.cats.implicits._
 import caliban.schema.Schema.auto._
@@ -237,13 +237,13 @@
   .name("overrideName")
 
- + diff --git a/docs/docs/introspection.html b/docs/docs/introspection.html deleted file mode 100644 index 07a0443d20..0000000000 --- a/docs/docs/introspection.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - Introspection | Caliban - - - - - - - - -

# Introspection

Introspection queries are fully supported, which means you can use your favorite tool to inspect your schema and generate documentation for free.

Here's an example of documentation generated by introspection in Altair GraphQL Client (opens new window):

altair screenshot

It is possible to disable introspection when executing a query by passing Configurator.setEnableIntrospection(false) to the configure function of your http/ws interpreter.

- - - diff --git a/docs/docs/laminext.html b/docs/docs/laminext.html index 52ebd1fd21..0de6eccfc1 100644 --- a/docs/docs/laminext.html +++ b/docs/docs/laminext.html @@ -8,7 +8,7 @@ - + @@ -22,7 +22,7 @@ About

# Laminext Integration

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

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

"com.github.ghostdogpr" %%% "caliban-client-laminext" % "2.6.0"
@@ -69,6 +69,6 @@
       
       →
     

- + diff --git a/docs/docs/middleware.html b/docs/docs/middleware.html index f7596f61c0..aedc96dba8 100644 --- a/docs/docs/middleware.html +++ b/docs/docs/middleware.html @@ -8,7 +8,7 @@ - + @@ -22,7 +22,7 @@ About

# Middleware

Caliban allows you to perform additional actions at various levels of a query processing, via the concept of Wrapper. Using wrappers, you can:

# Wrapper types

There are 6 basic types of wrappers:

  • OverallWrapper to wrap the whole query processing
  • ParsingWrapper to wrap the query parsing only
  • ValidationWrapper to wrap the query validation only
  • ExecutionWrapper to wrap the query execution only
  • FieldWrapper to wrap each field execution
  • IntrospectionWrapper to wrap the introspection query only

Each one requires a function that takes a ZIO or ZQuery computation together with some contextual information (e.g. the query string) and should return another computation.

Let's see how to implement a wrapper that times out the whole query if its processing takes longer than 1 minute.

import caliban._
+   (opens new window)

# Middleware

Caliban allows you to perform additional actions at various levels of a query processing, via the concept of Wrapper. Using wrappers, you can:

# Wrapper types

There are 6 basic types of wrappers:

  • OverallWrapper to wrap the whole query processing
  • ParsingWrapper to wrap the query parsing only
  • ValidationWrapper to wrap the query validation only
  • ExecutionWrapper to wrap the query execution only
  • FieldWrapper to wrap each field execution
  • IntrospectionWrapper to wrap the introspection query only

Each one requires a function that takes a ZIO or ZQuery computation together with some contextual information (e.g. the query string) and should return another computation.

Let's see how to implement a wrapper that times out the whole query if its processing takes longer than 1 minute.

import caliban._
 import caliban.CalibanError._
 import caliban.Value._
 import caliban.wrappers.Wrapper._
@@ -106,22 +106,22 @@
 }
 

# Wrapping the GraphQL

If you need to implement new functionality that involves not just changes to execution but also to the underlying schema you can use the higher-level GraphQLAspect which allows full control of the resulting GraphQL that it wraps.

Here is such an example that is part of the federation package which makes a schema available to be used as a sub-graph in -a federated graph:

  def federate[R](original: GraphQL[R]): GraphQL[R] = {
-    import Schema._
+a federated graph:

def federate[R](original: GraphQL[R]): GraphQL[R] = {
+  import Schema._
 
-    case class Query(
-      _service: _Service,
-      _fieldSet: FieldSet = FieldSet("")
-    )
+  case class Query(
+    _service: _Service,
+    _fieldSet: FieldSet = FieldSet("")
+  )
 
-    graphQL(RootResolver(Query(_service = _Service(original.render))), federationDirectives) |+| original
-  }
+  graphQL(RootResolver(Query(_service = _Service(original.render))), federationDirectives) |+| original
+}
 
-  lazy val federated: GraphQLAspect[Nothing, Any] = 
-    new GraphQLAspect[Nothing, Any] {
-      def apply[R1](original: GraphQL[R1]): GraphQL[R1] =
-        federate(original)
-    }
+lazy val federated: GraphQLAspect[Nothing, Any] = 
+  new GraphQLAspect[Nothing, Any] {
+    def apply[R1](original: GraphQL[R1]): GraphQL[R1] =
+      federate(original)
+  }
 

# Cost Estimation

The queryCost and maxCost wrappers as well as their variants can be used to estimate the cost of a query, however they require a bit more set up to work properly.

These wrappers are in the CostEstimation object which also comes with a special directive that can be used out of the box to instrument your schema for cost analysis.

Given a schema in which different fields have different costs to execute, either because they require additional network or computing resources, or database access, or they @@ -185,13 +185,13 @@ nested field b |-------------------|

which makes it easy to spot that e.g field a and field b could be resolved in parallel.

- + diff --git a/docs/docs/optimization.html b/docs/docs/optimization.html index 3719449a04..439161f9ce 100644 --- a/docs/docs/optimization.html +++ b/docs/docs/optimization.html @@ -8,7 +8,7 @@ - + @@ -22,7 +22,7 @@ About

# Query optimization

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).

We might want to:

  • cache identical queries (deduplication)
  • batch queries to the same source

This is possible in Caliban using the ZQuery (opens new window) data type.

Additionally, one may want to perform optimizations based on the fields selected by the client. + (opens new window)

# Query optimization

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).

We might want to:

  • cache identical queries (deduplication)
  • batch queries to the same source

This is possible in Caliban using the ZQuery (opens new window) data type.

Additionally, one may want to perform optimizations based on the fields selected by the client. This optimization can be achieved by field metadata from Caliban that can be referenced in your query classes.

# Introducing ZQuery

A ZQuery[R, E, A] is a purely functional description of an effectual query that may contain requests to one or more data sources. Similarly to ZIO[R, E, A], it requires an environment R, may fail with an E or succeed with an A. 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.

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.

val getAllUserIds: ZQuery[Any, Nothing, List[Int]] = ???
 def getUserNameById(id: Int): ZQuery[Any, Nothing, String] = ???
 
@@ -157,11 +157,11 @@
       ←
        
-        Validation
+       
+        Interop with other libraries
       

- + diff --git a/docs/docs/relay-connections.html b/docs/docs/relay-connections.html index d2f021eec5..bca56216fe 100644 --- a/docs/docs/relay-connections.html +++ b/docs/docs/relay-connections.html @@ -8,7 +8,7 @@ - + @@ -22,7 +22,7 @@ About

# Relay Connections

The GraphQL Cursors Connection Specification is an additional spec that extends GraphQL to support paginating over collections in a standardized way, defined by facebook's Relay GraphQL client (opens new window).

The spec defines several types:

  • Connections - the paginated 1:N relationship itself
  • PageInfo - an object describing the pagination information of the current relation
  • Edge - a type describing each item in the pagination
  • Node - the type that's being paginated over

An example query for a connection field looks something like this:

{
+   (opens new window)

# Relay Connections

The GraphQL Cursors Connection Specification is an additional spec that extends GraphQL to support paginating over collections in a standardized way, defined by facebook's Relay GraphQL client (opens new window).

The spec defines several types:

  • Connections - the paginated 1:N relationship itself
  • PageInfo - an object describing the pagination information of the current relation
  • Edge - a type describing each item in the pagination
  • Node - the type that's being paginated over

An example query for a connection field looks something like this:

{
   queryName(first: 5, after: "cursor") {
     pageInfo {
       hasNextPage
@@ -142,6 +142,6 @@
       
       →
     

- + diff --git a/docs/docs/schema-comparison.html b/docs/docs/schema-comparison.html index 3e73fc4211..046d19735c 100644 --- a/docs/docs/schema-comparison.html +++ b/docs/docs/schema-comparison.html @@ -8,7 +8,7 @@ - + @@ -22,7 +22,7 @@ About

# Schema comparison

The object caliban.tools.SchemaComparison exposes a compare function that compares 2 schemas from different origins. It takes 2 SchemaLoader as arguments, which you can build with one of the following constructors:

  • fromCaliban: pass your GraphQL object from Caliban
  • fromFile: pass the path to a file containing your schema in the GraphQL IDL
  • fromString: pass a string containing your schema in the GraphQL IDL
  • fromIntrospection: pass the URL of a GraphQL server supporting introspection

The output of compare is a Task[List[SchemaComparisonChange]], with SchemaComparisonChange being a sealed trait representing the various kinds of changes. SchemaComparisonChange#breaking indicates if the change is breaking, such as removing a field or a type. SchemaComparisonChange#toString will return a nice description of the change.

The following example will compare the schema obtained by Caliban with a schema defined in a string and print the differences.

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

- + diff --git a/docs/docs/schema-reporting.html b/docs/docs/schema-reporting.html index 7ad729439b..97e355b190 100644 --- a/docs/docs/schema-reporting.html +++ b/docs/docs/schema-reporting.html @@ -8,7 +8,7 @@ - + @@ -22,7 +22,7 @@ About

# Schema Reporting

The caliban-reporting module allows you to integrate with Apollo's schema reporting protocol (opens new window). + (opens new window)

# Schema Reporting

The caliban-reporting module allows you to integrate with Apollo's schema reporting protocol (opens new window). This enables your servers to automatically publish updated schemas on start up without involving any additional tooling.

You can enable the settings by providing the ReportingDaemon to your Runtime during setup.

// Define your GraphQL schema normally
 val api: GraphQL[Any] = 
   graphQL(RootResolver(Queries(characters = List(Character("Amos"))))) 
@@ -64,11 +64,11 @@
       ←
        
-        Server code generation from schema
+       
+        Getting Started
       

- + diff --git a/docs/docs/schema.html b/docs/docs/schema.html index a8be30bd9c..0b302a3fed 100644 --- a/docs/docs/schema.html +++ b/docs/docs/schema.html @@ -3,12 +3,12 @@ - Schemas | Caliban + Schema generation | Caliban - + @@ -22,7 +22,7 @@ About

# Schemas

A GraphQL schema will be derived automatically at compile-time (no reflection) from the types present in your resolver. -The table below shows how common Scala types are converted to GraphQL types.

Scala Type GraphQL Type
Boolean Boolean
Int Int
Float Float
Double Float
String String
java.util.UUID ID
Unit Unit (custom scalar)
Long Long (custom scalar)
BigInt BigInt (custom scalar)
BigDecimal BigDecimal (custom scalar)
java.time.Instant Instant (custom scalar)
java.time.LocalDate LocalDate (custom scalar)
java.time.LocalTime LocalTime (custom scalar)
java.time.LocalDateTime LocalDateTime (custom scalar)
java.time.OffsetDateTime OffsetDateTime (custom scalar)
java.time.ZonedDateTime ZonedDateTime (custom scalar)
Case Class Object
Sealed Trait Enum or Union
Option[A] Nullable A
List[A] List of A
Set[A] List of A
Seq[A] List of A
Vector[A] List of A
A => B A and B
(A, B) Object with 2 fields _1 and _2
Either[A, B] Object with 2 nullable fields left and right
Map[A, B] List of Object with 2 fields key and value
ZIO[R, Nothing, A] A
ZIO[R, Throwable, A] Nullable A
Future[A] Nullable A
ZStream[R, Throwable, A] A (subscription) or List of A (query, mutation)
Json (from Circe (opens new window)) Json (custom scalar, need import caliban.interop.circe.json._)
Json (from play-json (opens new window)) Json (custom scalar, need import caliban.interop.play.json._)

See the Custom Types section to find out how to support your own types.

If you want Caliban to support other standard types, feel free to file an issue (opens new window) or even a PR.

# Enums, unions, interfaces

A sealed trait will be converted to a different GraphQL type depending on its content:

  • a sealed trait with only case objects will be converted to an ENUM
  • a sealed trait with only case classes will be converted to a UNION

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 _ which is not queryable.

sealed trait Origin
+   (opens new window)

# Schema generation

A GraphQL schema will be derived automatically at compile-time (no reflection) from the types present in your resolver.

If you're more interested in the schema-first approach, it is also possible to generate the Scala code from a GraphQL schema file.

The table below shows how common Scala types are converted to GraphQL types.

Scala Type GraphQL Type
Boolean Boolean
Int Int
Float Float
Double Float
String String
java.util.UUID ID
Unit Unit (custom scalar)
Long Long (custom scalar)
BigInt BigInt (custom scalar)
BigDecimal BigDecimal (custom scalar)
java.time.Instant Instant (custom scalar)
java.time.LocalDate LocalDate (custom scalar)
java.time.LocalTime LocalTime (custom scalar)
java.time.LocalDateTime LocalDateTime (custom scalar)
java.time.OffsetDateTime OffsetDateTime (custom scalar)
java.time.ZonedDateTime ZonedDateTime (custom scalar)
Case Class Object
Sealed Trait Enum, Union or Interface (see below)
Option[A] Nullable A
List[A] List of A
Set[A] List of A
Seq[A] List of A
Vector[A] List of A
A => B A and B
(A, B) Object with 2 fields _1 and _2
Either[A, B] Object with 2 nullable fields left and right
Map[A, B] List of Object with 2 fields key and value
ZIO[R, Nothing, A] A
ZIO[R, Throwable, A] Nullable A
Future[A] Nullable A
ZStream[R, Throwable, A] A (subscription) or List of A (query, mutation)
Json (from Circe (opens new window)) Json (custom scalar, need import caliban.interop.circe.json._)
Json (from play-json (opens new window)) Json (custom scalar, need import caliban.interop.play.json._)

See the Custom Types section to find out how to support your own types.

If you want Caliban to support other standard types, feel free to file an issue (opens new window) or even a PR.

# Enums, unions, interfaces

A sealed trait will be converted to a different GraphQL type depending on its content:

  • a sealed trait with only case objects will be converted to an ENUM
  • a sealed trait with only case classes will be converted to a UNION

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 _ which is not queryable.

sealed trait Origin
 object Origin {
   case object EARTH extends Origin
   case object MARS  extends Origin
@@ -74,9 +73,8 @@
 object Role {
   case class Captain(shipName: String) extends Role
   case class Engineer(specialty: String) extends Role
-  
   @GQLValueType
-  case class Proxy(pilot: Pilot)
+  case class Proxy(pilot: Pilot) extends Role
 }
 

This will produce the following GraphQL Types:

union Role = Captain | Engineer | Pilot
 
@@ -93,7 +91,7 @@
 }
 

If you prefer an Interface instead of a Union type, add the @GQLInterface annotation to your sealed trait. An 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.

If you prefer to have a Union type instead of an Enum, even when the sealed trait contains only objects, add the @GQLUnion annotation.

# Case classes and sealed traits

The transformation between Scala types and GraphQL types is handled by a typeclass named Schema. As mentioned earlier, Caliban provides instances of Schema for all basic Scala types, but inevitably you will need to support your own types, in particular case classes and sealed traits.

Caliban is able to generate instances of Schema for case classes and sealed traits. You have two choices for doing that: auto derivation and semi-auto derivation.

# Auto derivation

Auto derivation is achieved easily by adding the following import:

import caliban.schema.Schema.auto._
-

Using this import, Caliban will generate Schema instances for all the case classes and sealed traits that are found inside your resolver.

Auto derivation limitations

Auto derivation is the easiest way to get started, but it has some drawbacks:

  • If a type is referenced in several places inside your resolver, a Schema will be generated for each occurrence, which can lead to longer compilation times and a high amount of generated code (a sign of this is that the compiler will suggest increasing -Xmax-inlines in Scala 3).
  • When a Schema is missing for a nested type inside your resolver, it can sometimes be difficult to find out which type is missing when using auto derivation, because the error message will mention the root type and not the nested one.
  • The macro that generates the Schema instances sometimes gets confused when there are a lot of nested or recursive types, and can mistakenly generate a Schema for types that already have a Schema in scope. For this reason, semi-auto derivation is recommended for non-trivial schemas.

# Semi-auto derivation

Semi-auto derivation is achieved as follows for each type that needs a Schema instance (MyClass in the example):

In Scala 3, derivation doesn't support value classes and opaque types. You can use Schema.genDebug to print the generated code in the console.

# Combining auto and semi-auto derivation

For some types such as enums, it might be desirable to use auto derivation to reduce boilerplate schema definitions:

# Deriving fields from case class methods (Scala 3 only)

In certain cases, your type might contain fields whose value depends on other fields. For example, you might have a Person type with a fullName field that is derived from the firstName and lastName fields. In this case, you can use the @GQLField annotation to indicate that the field should be derived from the method with the same name.

import caliban.schema.Schema
+

Using this import, Caliban will generate Schema instances for all the case classes and sealed traits that are found inside your resolver.

Limitations

Auto derivation is the easiest way to get started, but it has some drawbacks:

  • If a type is referenced in several places inside your resolver, a Schema will be generated for each occurrence, which can lead to longer compilation times and a high amount of generated code (a sign of this is that the compiler will suggest increasing -Xmax-inlines in Scala 3).
  • When a Schema is missing for a nested type inside your resolver, it can sometimes be difficult to find out which type is missing when using auto derivation, because the error message will mention the root type and not the nested one.
  • The macro that generates the Schema instances sometimes gets confused when there are a lot of nested or recursive types, and can mistakenly generate a Schema for types that already have a Schema in scope. For this reason, semi-auto derivation is recommended for non-trivial schemas.

# Semi-auto derivation

Semi-auto derivation is achieved as follows for each type that needs a Schema instance (MyClass in the example):

In Scala 3, derivation doesn't support value classes and opaque types. You can use Schema.genDebug to print the generated code in the console.

# Combining auto and semi-auto derivation

For some types such as enums, it might be desirable to use auto derivation to reduce boilerplate schema definitions:

# Deriving fields from case class methods (Scala 3 only)

In certain cases, your type might contain fields whose value depends on other fields. For example, you might have a Person type with a fullName field that is derived from the firstName and lastName fields. In this case, you can use the @GQLField annotation to indicate that the field should be derived from the method with the same name.

import caliban.schema.Schema
 import caliban.schema.Annotations.GQLField
 
 case class Person(
@@ -114,13 +112,16 @@
 

The snippet above will produce the following GraphQL type:

type Queries {
   characters(origin: Origin): [Character!]!
 }
-

Caliban provides auto-derivation for common types such as Int, String, List, Option, etc. but you can also support your own types by providing an implicit instance of caliban.schema.ArgBuilder that defines how incoming arguments from that types should be extracted. You also need a Schema for those types.

Derivation of ArgBuilder for case classes works similarly to Schema derivation. You can use auto derivation by adding the following import, or via the derives keyword (Scala 3 only):

Or you can use semi-auto derivation as follows:

TIP

There is no ArgBuilder for tuples. If you have multiple arguments, use a case class containing all of them instead of a tuple.

# Custom types

Caliban provides auto-derivation for common types such as Int, String, List, Option, etc. but you can also support your own types by providing an implicit instance of caliban.schema.Schema. Note that you don't have to do this if your types are just case classes composed of common types.

An easy way to do this is to reuse existing instances and use contramap to map from your type to the original type. Here's an example of creating an instance for refined (opens new window)'s NonEmptyString reusing existing instance for String (if you use refined, you might want to look at caliban-refined (opens new window)):

import caliban.schema._
-implicit val nonEmptyStringSchema: Schema[Any, NonEmptyString] = Schema.stringSchema.contramap(_.value)
+

Caliban provides auto-derivation for common types such as Int, String, List, Option, etc. but you can also support your own types by providing an implicit instance of ArgBuilder that defines how incoming arguments from that types should be extracted. You also need a Schema for those types.

Derivation of ArgBuilder for case classes works similarly to Schema derivation. You can use auto derivation by adding the following import:

import caliban.schema.ArgBuilder.auto._
+

Or you can use semi-auto derivation as follows:

TIP

There is no ArgBuilder for tuples. If you have multiple arguments, use a case class containing all of them instead of a tuple.

# Custom types

Caliban provides auto-derivation for common types such as Int, String, List, Option, etc. but you can also support your own types by providing an implicit instance of Schema. Note that you don't have to do this if your types are just case classes composed of common types.

An easy way to do this is to reuse existing instances and use contramap to map from your type to the original type. Here's an example of creating an instance for refined (opens new window)'s NonEmptyString reusing existing instance for String (if you use refined, you might want to look at caliban-refined (opens new window)):

import caliban.schema._
+implicit val nonEmptyStringSchema: Schema[Any, NonEmptyString] = 
+  Schema.stringSchema.contramap(_.value)
 

You can also use the scalarSchema helper to create your own scalar types, providing a name, an optional description, and a function from your type to a ResponseValue:

import caliban.schema._
 import caliban.ResponseValue.ObjectValue
 
-implicit val unitSchema: Schema[Any, Unit] = Schema.scalarSchema("Unit", None, None, None, _ => ObjectValue(Nil))
-

If you are using a custom type as part of the input you also have to provide an implicit instance of caliban.schema.ArgBuilder. For example here's how to do that for java.time.LocalDate:

import java.time.LocalDate
+implicit val unitSchema: Schema[Any, Unit] =
+  Schema.scalarSchema("Unit", None, None, None, _ => ObjectValue(Nil))
+

If you are using a custom type as part of the input you also have to provide an implicit instance of ArgBuilder. For example here's how to do that for java.time.LocalDate:

import java.time.LocalDate
 import scala.util.Try
 
 import caliban.Value
@@ -163,15 +164,7 @@
 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).
-For some time formats you can also specify a specific DateTimeFormatter to handle your particular date time needs.

# Code generation

Caliban can automatically generate Scala code from a GraphQL schema.

In order to use this feature, add the caliban-codegen-sbt sbt plugin to your project/plugins.sbt file:

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

And enable it in your build.sbt file:

enablePlugins(CalibanPlugin)
-

Then call the calibanGenSchema sbt command.

calibanGenSchema schemaPath outputPath [--scalafmtPath path] [--headers name:value,name2:value2] [--packageName name] [--effect fqdn.Effect] [--scalarMappings gqlType:f.q.d.n.Type,gqlType2:f.q.d.n.Type2] [--imports a.b.c._,c.d.E] [--abstractEffectType true|false]
-
-calibanGenSchema project/schema.graphql src/main/MyAPI.scala
-

This command will create a Scala file in outputPath containing all the types defined in the provided GraphQL schema defined at schemaPath. Instead of a file, you can provide a URL and the schema will be obtained using introspection.

The generated code will be formatted with Scalafmt using the configuration defined by --scalafmtPath option (default: .scalafmt.conf). If you provide a URL for schemaPath, you can provide request headers with --headers option.

The package of the generated code is derived from the folder of outputPath. This can be overridden by providing an alternative package with the --packageName option.

By default, each Query and Mutation will be wrapped into a zio.UIO effect. This can be overridden by providing an alternative effect with the --effect option.

You can also indicate that the effect type is abstract via --abstractEffectType true, in which case Query will be replaced by Query[F[_]] and so on (note F will be used unless --effect <effect> is explicitly given in which case <effect> would be used in place of F).

By default the suffix Input is appended to the type name of input types in the derived schema. Use the --preserveInputNames flag to disable this.

If you use scala3, you can enable --addDerives flag to automatically add derives clauses to the generated code. It will add type class instance derivation that create schema.

In case you use derives and ZIO Environment other than Any, you need to pass type info or your schema generation will fail. Use the --envForDerives flag to -pass in the type alias for your ZIO Environment.

If you want to force a mapping between a GraphQL type and a Scala class (such as scalars), you can use the ---scalarMappings option. Also you can add additional imports by providing --imports option.

Since Caliban 1.3.0, you can generate schemas using an sbt sourceGenerator, which means your schemas will be generated every time you compile (or when you import your build into Metals (opens new window)). -This can be configured with the same settings as the client generators, but you have to specify .genType(Codegen.GenType.Schema) in the calibanSettings entry for a given file.

# Building Schemas by hand

Sometimes for whatever reason schema generation fails. This can happen if your schema has co-recursive types and Magnolia is unable +For some time formats you can also specify a specific DateTimeFormatter to handle your particular date time needs.

# Building Schemas by hand

Sometimes for whatever reason schema generation fails. This can happen if your schema has co-recursive types and derivation is unable to generate a schema for them. In cases like these you may need to instead create your own schema by hand.

Consider the case where you have three types which create cyclical dependencies on one another

import zio.UIO
 
 case class Group(id: String, users: UIO[List[User]], parent: UIO[Option[Group]], organization: UIO[Organization])
@@ -209,11 +202,11 @@
       ←
        
-        Middleware
+       
+        Code generation
       

- + diff --git a/docs/docs/server-codegen.html b/docs/docs/server-codegen.html index 74dab59ab9..c8f30b21ae 100644 --- a/docs/docs/server-codegen.html +++ b/docs/docs/server-codegen.html @@ -3,12 +3,12 @@ - Server code generation from schema | Caliban + Code generation | Caliban - + @@ -22,7 +22,7 @@ About

# Server code generation from schema

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

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

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

# Code generation

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

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

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

You then enable it in your build.sbt file:

import _root_.caliban.tools.Codegen
 
 lazy val myproject = project
   // enable caliban codegen plugin
   .enablePlugins(CalibanPlugin)
   .settings(
-    scalaVersion := "3.3.3",
-    libraryDependencies ++= List(
-      // the exact list of dependencies will vary with the libraries you want
-      "com.github.ghostdogpr" %% "caliban" % "2.3.1",
-      "com.github.ghostdogpr" %% "caliban-http4s" % "2.3.1",
-      "com.github.ghostdogpr" %% "caliban-cats" % "2.3.1",
-      "com.softwaremill.sttp.tapir" %% "tapir-json-circe" % "1.7.5",
-      "org.http4s" %% "http4s-ember-server" % "0.23.19"
-    ),
+    // add code generation settings
     Compile / caliban / calibanSettings ++= Seq(
       calibanSetting(file("myproject/src/main/graphql/myapi.graphql"))(
-        // important to set this. otherwise you'll get client code
+        // important to set this, otherwise you'll get client code
         _.genType(Codegen.GenType.Schema)
           // you can customize the codegen further with this DSL
           .clientName("NameOfApi.scala")
@@ -62,7 +54,9 @@
       ),
     )
   )
-

# Lazy evaluation

The main difference between generating code for client usage and for server usage is that on the server you need to account for +

You can also generate it manually using the following sbt command:

calibanGenSchema schemaPath outputPath [options]
+

Example:

calibanGenSchema project/schema.graphql src/main/MyAPI.scala --addDerives true
+

# Options

  • scalafmtPath: Specifies the configuration file for Scalafmt. Default: .scalafmt.conf.
  • headers: Provides request headers when schemaPath is a URL.
  • packageName: Overrides the package name derived from the folder of outputPath.
  • effect: Overrides the default effect (zio.UIO) for wrapping fields in Queries and Mutations.
  • scalarMappings: Forces a mapping between a GraphQL type and a Scala class (e.g., scalars).
  • imports: Adds additional imports to the generated code.
  • abstractEffectType: Indicates that the effect type is abstract. Fields in Queries and Mutations will return F[_].
  • preserveInputNames: Disables the default behavior of appending Input to the type name of input types in the derived schema.
  • addDerives: Adds derives clauses for type class instance derivation in Scala 3.
  • envForDerives: Specifies the type alias for your ZIO Environment when using derives and a ZIO Environment other than Any.

# Lazy evaluation

The main difference between generating code for client usage and for server usage is that on the server you need to account for code which should only be evaluated if the client requests the field!

You can annotate this directly in the graphql schema by creating a @lazy directive.

directive @lazy on FIELD_DEFINITION
 

You can then annotate fields in the graphql schema like this:

directive @lazy on FIELD_DEFINITION
 
@@ -71,7 +65,7 @@
     myField: String!
 }
 

And you'll get a case class which looks something like this:

case class MyType(myLazyField: zio.UIO[String], myField: String)
-

When implementing this, myLazyField will only be evaluated if the client requested it in the query

# Newtype declaration

The @newtype directive in caliban allows you to wrap your GraphQL fields into statically +

When implementing this, myLazyField will only be evaluated if the client requested it in the query

# Newtype declaration

The @newtype directive in caliban allows you to wrap your GraphQL fields into statically typed IDs for backend. For clients, they can use the GraphQL as before and do not have to adjust their typing, or optionally can generate stronger typed IDs using the directive.

In the following example we want to encapsulate id : ID as FooId for better type safety, so @@ -128,13 +122,13 @@ }

- + diff --git a/docs/docs/stitching.html b/docs/docs/stitching.html index f6142b5913..ee4b89d3d2 100644 --- a/docs/docs/stitching.html +++ b/docs/docs/stitching.html @@ -8,7 +8,7 @@ - + @@ -22,7 +22,7 @@ About

# Stitching

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

In general, Federation should be your preferred choice.

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

# Dependencies

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

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

# Stitching in Action

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

import caliban._
@@ -181,6 +181,6 @@
       
       →
     

- + diff --git a/docs/docs/tools.html b/docs/docs/tools.html index 0ba2a0bba1..909e3a5265 100644 --- a/docs/docs/tools.html +++ b/docs/docs/tools.html @@ -8,7 +8,7 @@ - + @@ -22,7 +22,7 @@ About

# Getting Started

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

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

# Dependency

"com.github.ghostdogpr" %% "caliban-tools" % "2.6.0"
 
- + diff --git a/docs/docs/validation.html b/docs/docs/validation.html deleted file mode 100644 index 27b62974f8..0000000000 --- a/docs/docs/validation.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - Validation | Caliban - - - - - - - - -

# Validation

Caliban provides a little macro called gqldoc that can check at compile-time that a GraphQL query (a document to be exact) has valid syntax.

import caliban.Macros.gqldoc
-
-val query = gqldoc("""
-  query test {
-    amos: character(name: "Amos Burton") {
-      name
-    }
-  }""")
-

At runtime, it is possible to validate a query against your schema by calling the method check on your API.

def check(query: String): IO[CalibanError, Unit]
-

It is also possible to skip validation when executing a query by passing Configurator.setSkipValidation(true) to the configure function of your http/ws interpreter. This will slightly improve performance.

- - - diff --git a/docs/faq/index.html b/docs/faq/index.html index 7018415ee2..cfa2c8e089 100644 --- a/docs/faq/index.html +++ b/docs/faq/index.html @@ -8,7 +8,7 @@ - + @@ -22,7 +22,7 @@ About

# FAQ

# I don't know where to start 😥

No worries! Head to the Resources (opens new window) page to find a few introductory videos and blog posts. Once you're ready for more details, check the Documentation (opens new window). If you prefer looking at some code first, check this list of examples (opens new window).

If you're still lost, just come to the Discord channel (opens new window)!

# I'm getting a compilation error saying a Schema is missing, but I don't know which one.

Call directly Schema.gen[YourType] or just gen[YourType] if you extend GenericSchema. The error should be more detailed. It is also recommended to use semi-auto derivation instead of auto derivation, as it will tell you more clearly which type is missing a schema.

# I want to use Caliban, but I use Cats Effect / Monix instead of ZIO.

That's not a problem! Caliban has interop modules that "hide" the ZIO details and expose Cats Effect or Monix types instead. Check the interop docs (opens new window) for more details.

# My query fails with an "Effect failure" error. How can I get more details?

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:

  1. If you fail with a CalibanError.ExecutionError, it won't be wrapped by Caliban so the original message will be displayed
  2. Using the wrapper @@ printErrors will print the full error to the console
  3. Using mapError on your interpreter lets you unwrap the CalibanError and return your inner exception instead

# I have more than 22 fields in my Query, I can't create a case class for it.

Instead of one huge case class with all your fields, you can create smaller case classes and combine GraphQL objects using |+|.

val api1 = graphQL(...)
@@ -73,7 +73,15 @@
 val interfaceType = Schema.gen[Any, Interface].toType_()
 
 val api = graphQL(RootResolver(Query(A("a"), B("b")))).withAdditionalTypes(List(interfaceType))
+

# Can I check that a GraphQL query is valid at compile-time?

Caliban provides a little macro called gqldoc that can check at compile-time that a GraphQL query (a document to be exact) has valid syntax.

import caliban.Macros.gqldoc
+
+val query = gqldoc("""
+  query test {
+    amos: character(name: "Amos Burton") {
+      name
+    }
+  }""")
 
- + diff --git a/docs/index.html b/docs/index.html index d900014330..8dbde86cce 100644 --- a/docs/index.html +++ b/docs/index.html @@ -8,7 +8,7 @@ - + @@ -22,7 +22,7 @@ About
hero

Caliban @@ -42,7 +42,7 @@ Functional GraphQL library for Scala

Get Started → -

High performance

While every public interface is pure and immutable, library internals have been optimized for speed.

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.

- +

High performance

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

Minimal boilerplate

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

Excellent interoperability

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

+ diff --git a/docs/resources/index.html b/docs/resources/index.html index 956212e300..3742e0f6b3 100644 --- a/docs/resources/index.html +++ b/docs/resources/index.html @@ -8,7 +8,7 @@ - + @@ -22,7 +22,7 @@ About

# Resources

# Talks

# Blog Articles

- +