From 6992a6be36c80064b02f14325837bacbe37a677a Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Sat, 20 Jul 2019 23:02:35 -0400 Subject: [PATCH 01/25] Initial codable support --- .gitignore | 8 +++++ .../UserInterfaceState.xcuserstate | Bin 48884 -> 50290 bytes Sources/Request/Request/Request.swift | 24 +++++++++++++ Tests/RequestTests/RequestTests.swift | 34 ++++++++++++++++++ 4 files changed, 66 insertions(+) diff --git a/.gitignore b/.gitignore index 78d01a9..8d2b6c0 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,11 @@ /.build /build /Packages + +xcuserdata +.build/ + +*.xccheckout +*.moved-aside +*.xcuserstate +*.xcscmblueprint \ No newline at end of file diff --git a/.swiftpm/xcode/package.xcworkspace/xcuserdata/carsonkatri.xcuserdatad/UserInterfaceState.xcuserstate b/.swiftpm/xcode/package.xcworkspace/xcuserdata/carsonkatri.xcuserdatad/UserInterfaceState.xcuserstate index 8e42e7fa7bb5ec29e24e8db24d794d811d51cd31..8956bcf4dc51a2ae7f10280f4778f0cd8a8fc84f 100644 GIT binary patch delta 21137 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 CRM83m delta 20054 zcmaL82V4}#|NnnGTkf_XM+fQUXcjEkqjv++LCOKr5p0-fEZ8;n zuF=?Q5;c|>HAbVx?r)a!lK9Q%|JTPXcY8ZK&)56?p1QNo%kdWL;C1cE^rhyu|d2E>9CkP0$DCYTH6f%#woSO~rX zi@;(a1I3^cRDo*H2%11MSO?aFZ@~tz5o`jRK|k06wt}5tKR5tRfRo@9xBxDKU%^B0 z8+ZgBgD2p3@D%(Z124ck@E&{sA8`s7;v!rhAC4Q~Bk+;yWdaU0wPcg5ZC z33xa@5trZ*cqAT$N8>Sg0-lEF;(2&Jz8II`avb7Ccrm^NFTqRkO1vI##oO?9d;`7_ z--K_*`|&OKR(u=29p8-~#1G+zaoK77d;AQ37r%$!#~C2EN}qMm4w5zRy=(M5Cyf4Qb1xPNphqbIf&FD zhmg9YC22)klQyI+X-C?V4x}ULO8St#WH1>*hLUMyI+;Ocl3Apb%qC?yWGkZAzaSP8m@4lmq2RIZ@7(3*}0= z$tZWqn+l{RP~p@>DwE2hq*OMQL*-I=R6aGCDxl_2bE$choPtyl)k3vWZB#qeL3L7H zR5!Jp>Y-Lq>!>Z%R%#oym)b{Npe|CEsLRw9>MC`Ox=!7oex~kI52#CsY&41_`x5GPo3`F)K2a%)5N#rbY5xI)oMD8MQg%deSCKJg;P}C%97A+ICh+0K$ zqIOY-s8iG<>Jx1gZ4zx39TgoD9T%MtofMrCofdsBIwLwSx+c0Ux+D5k^jP#n^rz^B z=rt{%Nt&kBXiZv&)~AQl2DBsXL_5}B>?MIKL{pk>T0v#@+ zW9c|Lo=%`A(OI;V&Zcwd0(w5ZfL=&{MK7Wk(=xh(uB5BzYPy+TMz_$t^a^@4y^Y>Z z@1S?myXd|20s0_)gg#22q<^3<(pTua^sn?o`U(9z{ha=j{)>LiFbvCZj2bhDQD-z5 zO-73`W=t4U#*C4fGZu^`W5rlA?u-ZH$#^l|jD(3`BAF;Anu%dznK&k%NnuhMDU;1i zV+xq*%mQX1^A%IhR4|oH71P8tGs~E6W;xTxtYtPZTbbR=0p=KUoH@gsXKpdKnLErc z%tPik<`3o>^NxAXd|*DZ1k11*tfq|BVy#&l)|Rzn?O6xbk#%C7Sr^uobz?nQA9gJ3 z&xWv}>;yK3jb-E5WHyD(Vx{b4b~ZbQoy*Q+=d%mgC2R>>%GR;|XXTdxSm7USuz^m)TqFZB}-N{e`{H{>HvwU$P%KoFh09 z$8l<$Ca1;ea6>pfPMa8tP%+)Qo`H2PE$4c;UTy`qlI!C(aND^Z+hc!!zg6BQH${J!D>m7!Q&>BeDMTh#VBa4K7n4+-3j$ie2v}eUj0IY~U<@#l z_sDw{-#oF*t)E;rXy zGf`#F0#gP4NQe|)$QwdqZ3n>Ame3I{%9~emH8bD)&3ZMqmDfw#={~?~g0r4OH55Fd1 zrOL7l^aw21f)>yU+CV$#0G*%$Xa7yk=Cbeby5X>eAl_YBf|`HL)ym@w^Na0&dxN7iL<1zZK!z;$o~+yp<$ugb5< zugh=9Z_0m^|0Msp5B&T&vVH+~kwfmwZ+({ai~KHf$h`rF7=dTJqUZA4Dn&1OMX$ha zKFRMOJt!$sZFF?OCmalb;TQtDj~sy$$Po_|H8%P|G_Hl1a0X{_4p+km;p(^st|@;g z|4sf#{#gD*{=59C{Et3dtTHxlYJ8ad+25w-gXB-dq=ji3Atc;b{`@l%Zl+isp)bR2 zaR+7j_Ne?9eECkO{Fnc=B{BW8Epd0;pU3jRJ#jDG8~4F|aX);l{4e=y`5XCL`8)Z0 z`3L#OK0M$HtnunO!rXT8L;_%&3K@gMMW_<8&Sei6Tf zU&gQCS0QEyu`v)cf|xPHOdw_oF*AsnL(F0=eq9BO|2z<7cOYh|LWY->8Z21H+ zUx@iBk4Ph}VW7fwA>5U?Zal6(at`6iJ10Q#)?Gisj|k;q#}fWT01-%xBZ7!vA_QXN zAQl9%V2Gj5p%5Dnu`q~D=p)8|0UHUi@GoH_Kf@;TuqhCmsDe%BVKazKK0!s6iLKvVh%Bvm`BVf77z=GuZTqui-j1f z(D4vUfY>C6B|fjXrzH0M(UCJdj; zh;>73`C2ko1xqIKaYLe7+oQsT*h*#StRAQ!XyhDD=JV7j_Fjs_l`XyAdG%%P-=EK;h1ys9-{{2EP`ll8p$E67T+ zimWDU$faa0SqHJT5c?Wp-#}~~#88*^EyOlJY-1nUpcF(l<1dgLBzu!m4#c*get_>d zwhq`oW+ks=6~s2Hl=SgR)`H!9f>^)&+`s|pFf#NtRgTG3f;N#`l*s)&@;2TP+jvK8 zS4;}lkJwEf=8^Z1-;sOCedK=f0C|u+1hJhE+XXRn?>!Lv4q|&Dwhv4>rtNd zA?FiaK@9PH53w^4I}5QN`pDN` zz6e=xx z`!l2m59tZ9TPjGO0myMwh!QfGhrGi>j^`nN`7b1XLj@_J5_rf6Dw2w#qNx}vmWrd| zA$AX9_aXKGV!uM{A;f-z*dvHN?xQAs0htc5C;tcXnX<{G;`JK`jqvDxQeWet!kQecs7qOTZ@#lX;XdG1KDW+;r6GAPaN~lt*j4G!p zsNhPfib5^iONgPUKrQlXh`oW>TZp}b*n5b5SW7KcDWMd61XIlr`>4_afndPo09Umk zVyc%HgxZKtDnYAxtB0?rHuAvQ)CSZ_01UMQ)MnI+0`MPTO{_viyq(&mRJjwW1jIj? zP}?#zazAx~_sIe3Aa#g3OdX+)Qpc#{5Ks^ZArL`8L%=}5Lcl?w)<>OGDxuDR5~SlC z1cQ`1Akak9+7<}3KKtY*FX2ZB)KwC0@jkf??(zu&4Y~4wJYsI>YxzavK|Q1%E0G`Z z$YS0xzaz&0?f>c|o~v~JNxkQlyr5oEuc&c12tonquN^0d2gwO>7YgHgAqsUHaf8ki3*&hNM74tZrIYSuC zCw^=RP_5^Wh*`D9BMcWtC{ZOmsy&Yy#iKg>*YKQb0xFCbrt=CCgp-7c!X#m`Fh!W^ zB}{|B2?A#b5TYvtZV8m`@P3NU1pUwoVFOQDDXbD!3u}Z+g|)&uVLb%M zL;(;4LNE@3AP9mX2!SB9PpJ3;vJHaqD#(7%_@S6=6%V%>f-n`_+5tGUOmY`3liWql z;M3o58-@K!%Wmf3!g;u@Jlw?pSXN_&O3*IhAs%_RaF6gi;a=fB;eO!(;Xw!@Ac$04 zO3)s4_zT8U5G1G=m9daCV8}4xWuEm41d~*(*Ac7m2H4Ff2oh08&L2=DXsXJ-BfO{N zz030^BVOf71V12&7CsWb;K?2fp9p^!J{A5Ud?tJ@{1bvy2$0{?AwX3k6M`%Vq!48H z312Efg>Qs!QB`{nL5>m>f_w-j^Hpt1KbDDxtwKa9Lak2jXHpT1NJSjj%_j)*cv5sg zq@ISpBbD_`!|*e-Xs}4xb&B||6HG(N>`Zi9!dAE(+oKzvB7Bc>YC-@6+@Z2C2GkG6>`lKnRK;D28AO z1SJrZ_K6bz9SI_2{jx8aDh8Oert(bFAShQc&EQv4!bI~#3zY>g;0vzg3tq$*T=ieW zVINhrMWQO+aK)k}q7qT5s7zEYst{EwKBWyCRs98y0)nP5ah54@x_F#!2%1$my*$nk z(OS_uCC)cIP79Cot-N1RpP{XolEsAfi}-n;Xp3m8Xq#xeXoqO0XqN~@M>_-^5TO3B z3j%c4kz z$mAE%J%MG9=q?0(J)-*%d@Z-QAcz&Pf;d6EAVKsuoBbl&vzX<5-T z)2GeKoS8ShFd=VRmUNyZy)YMo&2j;%ENdb7_5zL30Ikwj(l|{h%yLX+8z9(po~8sW zEu=+p;ZfFE>4oWI2@Hab=LN}v6q=#gsrCUNneS zPYjO=Q5D%sYY5W+eL{Ja7A;QI&Vvl`OmoeXM$l#gt+n(>dK5jHHl)YUMzk?)LZf=I9fBPY?1W$!ia^}}g@Fz;YTyA1J&}$? z;Y3U52nbF>aH^M%qN5==4Z-({>U=Y!L^@Sqxq?ojlj#%)&O(4f^4tnKjZUXgg+33# z69|4(T+c6v%%!KTqVwo{dNMtQo(jPQ2(Cl$69l&*Kel@OxrWlyX|yK0f}TOoq-Q~J z5rRt)TwX!XrsvReAwV6%RS2%3bzco*#m~hCik*|ov*q-X|CObLF6AL^KyVX5$Sn+g zm2IyeVr0zN*?Cj4R7KX%XfpbrB7q03pc~~VB!7nBmfS+IY07ZtR=V?lUHS{%O)r=K z0>K>!evw;b3Pu_M!ANB!ucSr&#MBy{@f%g;t)agaSguAA*V13pv*>m7`T?Q$AV4+p zG6WAG_;ocs8|R+d?)e{f=8$yIfq!VC8HD{ie<9hsH*ItzvHV)Vct}! zq2GZSeS)bA^db078Rh%v{mQx_?WOk#(ox-vF33usKQg^=q?@~g<4C^=%Igl%hg1Hp zSbj5Srq5qN9}+ARq-&rXp+{--F?w2$U=Z4?@sF!c(X#JRXz^!z=ra)fA-7Ood+wiW zl_xII(@@LySo!6upyX@83yi@8f)5xW_>2CTzD3`r@5sl=XUbFL@$zhW7zBSp@DhT* zAb7(MNd9i3=m*MpeUYjWot>xf*9}zI>Fd(;W98{rih{vO9Q{oB?RBa~p2ANzNTEN< zilbjCPrgmnnDY6gSP?o{J4_krZxD~=8u~5$j($&npg+=|7y$(DA@~5nM+iPaTmW$l z;$RH}7#w@fkn}sgT08((piO{ zL!ZfE@&%T?OfHiL@sSW8)yqugKaNHp(Zx{(vu9>XXGv67&tPVw+Q!Ue@|Z%18={LK zK4t|o2YpAGj0V2*`ILot6-I~7Do{PIV-_(*yr~v5GITkFxG}^{26C9LWQv(3%6phW z+*)}XMPBu2Sv6C~7nsK^Woidbn?u}!|K7kCh)TCaN4Z7vXH}B)ndwt!#RSePoSCj- zZeiMag{^!BD|B_QvLKWfWsHiMIYo7053`cL5d98u8|8(F6nz-DGVyZ}v3b(DsvKW4 zXo#V*`g(}l$-7lQZDcn8WBPuG+w+b5KwvZ5m>v92xyax>%ua|q{PWWuW-tE}vhA22 zW*@|5j{p32kU`5`J51* zkYe)ER4wK%bDuBg9>l$Rms9&MV2EM+Pm0Uj&yNzP$V~6$;9kPf#o_@n;p#R zutQi~b|^cH)noP9;j97U3-M5hkB4{|#3w);)y9bsmq0uM;*k)Kf_OBt*E)6-I~t`? z*mFJ!MuXk_Cl-Zj3`EaF`C|-kKy*NZj&lPaAs)|DY4+1i6lUtqdMt-{>_AVzda>Ry z;Zaf2!d})(fJRiP@n?ON?YF|Nd8B3l%a146K!{K3VS^x^sK{ux95G&b#b-OS;cNs7 zZgwJzXp36V`tTfyeAxh$$ASrE^MI2uN%#trNgcDg`o1v{0U#uh+a3h``+=d567 z2u8EBAfC%Np?UJ|WOVP4EVQ>GFFQ}F*tjeppIykx{#Qmh%2)*P$$Z8sC?gsu24>|I z7R>aUDNQ%@?cO*rm{930W2^qxP0*ZzT?+AO{7niJDJ@1aR>AfNEZ4J*Y!lneE@NBR zR<@08XFJ$Vwu|j%ksoG2d?v&ZG^&@gAwCDGyjNQi`;Qg>4;_@E$AjIMSpC69W(|Xxs>~V-A`;`341*cfFL*l*vBZUpRm8PPuV}%XY6yZTfsI&41#zo z#A_hl4)JQVy<$tdOA`A^P_l~si+#<$Vc)XvAddW54{-&=n;?38Z+?OO$bJ&AoIp^; zfk}VI*36iJ`3J;ndCS)&{k!2DsAn9>Q3_wh2)vgQD!dhjGUaV(P{IL-H^`AM>i&0w z`?s_bnRaKy9BNhK^%Rs*5fi~P~rgVmk@20N{ zD!AdC0XKphi6o5@lyRduL(B_pQ}q$l3FYNE`&}J2;&n(QFmg8SAW%kr* z;j^b^NM|Bo>9nl>oYc(BMLlIEny^HsPs@>_eND(y{M4l|uV7l>w9EpOMV7BHqowl-KhN$g0mH*qYoC|1Fa8dkH)l|1H{o(UDf7r&K!CUzk+k& zTshQ%bwRuv;>%ZX=vg1<1@RuQuHXm3Trje22p6iT?;LKl65>a$ za$(#AE}WZ)&P%umE|QDlqPZ9@mWxAS^@5wExX`&#hJ3jR;+rA93gUQ@z82!&Kz#i_0i36dyuSaB$dmAW z{pSFirVOF4{~LO7-uTLQZ>ZWXJ<^w%Tx|GtY!_25kJ>yu9QQY(AIKgTsc?4RdQ8aHCMweJRj?!h$(|<&;Av{qFN}3pcQGN~2|6l;q85S(i_$l~ZmbH?VT5&22^xJ@9?# z`32BLk4C!&9*uH4xjh4GG~8~qMuQ*t=hyFg{0#nQomZOXFn2^@*Eh7r<`r62wnI z{0B6x#Lp}C^!k`{H@VwN2<|5I?8rUol$7{mH%jyD#TnLHxq!*&z1@^%vY*4mF(@A&w^Se^;N6YG~uy zfBFkGTrgUVg!m=CwZAOyjt`S&4-5qieQUqybk!KOL4W5T|4*NSY!Bmgy$XqY?;-5L!y z{^=Lww1$RU6qgzve}0JW&|#C5Ij5yhmBuSSN@t~N7=%Yj{>~p0GSEy)vm&M0 z(wWj}nbO{&dhy{=6EpIqnS~e71_t#JqYM=@R*5xxM#|Zq(I}q97mSS6O-#)c9joj} zPOc^&q&UCIY4{LbD{C~>kII}Wl}-ywpIV~e58<6$+dRILJ?%|n)R^9S4`9?f_=KNj{J;mMCV+?%##`*^YjtdG7 z2^}9cA$+1FA~GsEDmE@YVNzmJvch=H53Ep5$QccFIVsmxV13%MiGmox9Kj+%gJ6x| zjNrcDiQolV8qmgcFkNgIHX1X*>@g242}{Ltu>x!^R)j6VO0jaR6061(*tggr>BZEhFP7Pl+-HT(wt<3I!n09w8n z_?Pne@8>`GEeJL$&LLI9)bwJa3eyXva!eo+3`N5<3xSisUEqTrDSQ%f=skfEXwlw6 zWF@je?+G}gHv~LHk)ru%S-Ks)4bY9=2UsCmC0c`4mcJ3L7i|z7M(+h2M{fk25uFoV z6kQRarC!l3^iIGVwEy1_?f0KV*PvynJ@gs075_K-FB$!j5umjS0`0_CL%Z;`(0YU| zlZH0XFJo3RtI^hZG@oR?Wi~S3G5eSU%pv9o+Cq<}am-b;h5j+~JK8+|oQ-4?*=)7| z?R{Us7Nh;{4QS-r%)aG>9L=HHfwrPAKwHokqfO{H(O&XL+!OAp+C;S^wG=g3np%e1 zezot_eo#BFc1i7u+BLP8Y99w-gYZG*Ae})Y2e}Oj927JtWYG9Q69%mxv~AFiK?eri z8uUP&QrA~EQnymKSNBklP>)xas?SuPtv*+Mf%;eKi`C22E7hyjm#TNG_o%N>U!}fA zgVoU17^N{r!x(J?w9v59aMp0s@X+v*X@qM?G$J*kHDWckY3$QDt#MZ4oW@0s%NkcT zZfo4txUcc6#v6@y8Xq)1X=0kmn%SDOH0Nl}(_E;zNK>X+u34p7qgkuDT(ehmrRHkQ zJ}r@!rj~)$C@n)RV=YrHb1ergXDwGPcdhYS6SO93MQBB7ZPMDMbxb@+tRdDCYl~$% zVqNhtvA)^QS2;s6}yW)#ol6H@mO(yc$_#`94ZbI zhl?fRNO7yUUEC?|7War(h*yc%h`$!E7jG2zi?@k)iuZ{3i4Tg8h>wd;iO-17i7$$; zh_8!(6yFm6BEBzvD1Iz{Dt;~#zZAa~ztt9M)7q@In)V#+V(k*`GVKcO*MrHy!ol=l zc5u?*yup(PPaRw^_~78PgU=1VF!+*Ah)%3dyv`(@B%Pmh9_c*Md8+elNX(FoAz4GR zhvW`9Hss=v%R{aXxvuM{8?GzSjns|SJ*4}C?s?sdx|fH>50wth8JahA^3Z2PWgmwL zhJj(kFzK+F!wQGZ88&a&OFf`R=uvtiz3F<3^kjNauUPN8-UGdddXMy;=qKyv>rc_2 zraxW(ss4NYkHZDS!SKZ4xx@2^PZ>UK_}$^phW|PI-rkjahCq%*e#Z-N@6(+sM~wtWki`IHO>rP@^!TRHJmGOe3jL zj!~YGY_ic*qXMHDMzf6Sj5ZiuFnVdMXY6I1ZY($MHtsY2#(2H)2IC#Z2aFFHA2B{= ze8TvY@%P4Ojejt{W_;iHk?|Abr^YXgUm3qPerrOR3^p+^8DTQYWQ>WGiM@%BNr1^X zlVFnxCKF8}OrlH@Oma znrt`OX>!@*rRh*p57Tth64RBYhfGhKo;5vZdcpLj={?g2rVmXYnLaUnYWmFdt?7F+ z+H8=ShMAVx5VN6XdS=7TEX|zEoXuR#Jj{a463i0KlFd@h(#q-Hs0d1edDzA{^E zCO0cGTVhsfCM!3qG^;jSYj)i1vH2i#NAq~|x#rF0-R8aKE6rD%Z!q6szRP@%`Cjw= z<_FCWn;$j5V1Cv7y7^7>+vdNR-!p$;{>uD~1!XbRLeFBj#R!X07KRo^7A6*E78VxX z7QPl^EdngYSp-{zT7+4ITSzP-Eeb4_T5PtsXz|uk-_qAIRc5)^vdps5vf6T~$%bzVDTRyY=)AFU|Tg&&BAFTvd z>Q?$zR#rAvc2*8nPF5~fZdM*vURL2&601n7XscMOc&kZPNmeOVX;zD@I;{3v-LV!~ zTUw8|&bOXrJ;!>UwQPZPv30feQtLYF2J1%aX6qK~9_tm>8?ComZ@1oQz1Mob^+D^y z))%ZVTmNGH!uplpLp+s(FHY`59&u-#?5$9AvnS=)2A7i=%tUa`Gqd&Ble+grAGY(Lo<*p0Qz zva7WF*6w?|$96C6UfaF1`(RJmtJ`bZi|q&753wI=Z)|U2Z)I<5?_}>{?{4pDKi)pv zKGA-PeS!T<``PyM>=)WEwwFQsCH77BE%t5p9rj)J%k6vZSK67Scew0u)#19sO^2TxZaF-0c<%7R;V*~x4j&ycN8C}%QQL8p zqrIb(qpPEbqqn11(HTPTxB1cG~ZB(CLWNNvG3JXPwSD-Ez9) z^wb$Rlg=V%)_IV#rn9#55a(ge!<}uN9h}h^(Amw|!`a)}*LkdSpmUIOmUFT58s`(v zPhB)!oLr(^X1RRjB6BHnS>htAacOpGb?I>FcIkCl>9X3T&t8_csQrBG9eAhD9)vhO9AG>L}IlINU6}l~Qle-nWmAEZ+Tjtj0)+uva?zX~h zmD?J(wQk$ocDsG&w%_fD+cCG3Zl~RDxc%hz$nCw`CwJgZx{KUd_d)KO?%M7~?xybM z?w0P>?zZms?vCy*?r!d}?z7!n-FLg+_8>jRc=&sSc}(<(^oaII_Q>|g^O)jM;4#yq z&|{9rJdYBON{?!fT8~DLW{*}6S-Z#A9_u`IdYtw+>v7)WlE+n#8y-J--1fNZ@xbG) z#|Mv3o|q@@NqUMr8Bfkr-BZ)k+H->E3{QpUPR|>jpS%pbyu8MFg?NQ|g?q($rFms~ zWqaj$P4SxMHQj5bm&|L4SE*Np*HW)KFNIf=*GjK7UR%6&dhPbw>vhQMh}UtM*GaEy zUiZEJ@_Os_!CT;sdsE)DH|MSHJ<{9I+sNC*+sxa-+sfO<+uqyJJHmUqccb?<@0&gX zpAkOZK0!XAJ`;Q<`o#OB`(*j#_~iRc^(pX~;WNue?o;AZ=2PiY>r?O3=+o@8%BRm~ ztItuN6F#SX&ib79x#V-z=Z4QuKC-7i&wXC_yz+VN^Va9R&qrU(7xx|M>*Jg0TjKkT z?^)m9{nY$){D%7J`x*F|_}Th7_&NKz`FZ+z`=KGU-$cJ?zgWKnzZAbTzf3==U!mVz zza@T6el33OeqDY&ek=Xf_l zKh}Sue}=!*Ki7Y<|1|#@{)PT?{TKKz@~`t(_&514^KbQU_wVvw?%(Ub%72ajVgFwO zgaKv&69Z-hGzDx4xDaqN;OBrl0e1tQ1jt?mya{+8@F@@k5`k2pI8ZlmSm5x$(Sc(E zjRQ>sT>=9FLjuPKh6hFk#stO%CIsdN&JHXMtO%?QtPN}kYzk}%Y!B=T+z_}qa7*B} zz#W0R1NR2*4?GljB=F8SY@E@!pm9^j)sNda?(Dd$<8F-mY22-G563+p_j24{+Ko4G$U_WE5l)WFBN0 zhs1>>gd~O}hopw2hh&CihvbHogscoX9`akLMyO+GROrmmg`tZ>VQ6t^b!b!Qve4Gh z_R!AI?$C9in?n0Tw}tKw{VsHW=)ur)p%+7MhdvK|8TvZ(UFgU0*mz>Ra6B_!Z@j_y zk>f{?A0r!YJl=G?`FN}GHsiy_Paa=8e$)6X`2)0uv1}Y!p?==3A-2e zAnak-qp&AoPs5&ty$E|XK|H~JLhOWj6S^iGoNzl_5RTq6=EBv(HN%I68-^Q)n}u73 z+l1SNJA^xhj|~qB4+#$oj|h(nj}4Cx&k4^9pA%jYUL9T=-Vojt-V)v(-WA>xzA}7! z_^$9h;d{gPhaU_-5`HZFMEL3OGvSXWG83&QN+!;k*fMd?#2XXeN^l7!p(U(DTQXcS zLNZEXC^3?l$Rv&uH;ISDTjDPXlmtscB?*!wNuFeyWV&RQWS(S!WRXNBSt@Cltdnez zY?f@5?2zo1?3Eml9F|;?T$Nmx+?4zzxh?rca!>NB(3ychn42zr?84;NlnHf1f5=JhG zEQ_p+tck3PR75sMwnly(xju43vcjocskW90j&kx^r#a-*uFzKJ>+ zbs_3<)U~J^QFo)BMEw!6iLsHf(Xp|y@v)O)lVVe1(_>|svGUmN*h8`R;@CKwxbV2C zadYD4$9)yIIIb+NF0LW2F|IkTC9W-QP29S;Z{s$_ZHwCxw>$2;xYKcG<8H=1iTfk& z&$w4{Z{ps^eToP1WV}xN(0IN0;qfElN5vb)8^xQ(o5u&mXUA8@uZuq)|0-c{f@6YL zf^UL`d5` zurJ|Y!jXjI38xZnCj6XmJK>jvdkGH`9wt0W_&wo|NotcUCrKvFoYXRD&!iiZ-X`LS zR3e?oCTb@RPaK&zI?*W6B+)FiHj2DiN%Sf zi4}>}iM5Fhi7OIUC-xL*nMdEs5I`cP3s=e3>*f$s;K}sU&G-(xIf&NoSMJ zCtXbXG3kEN!=y(^zbE~X^gQWB(ubr^$y~B#vN%~MSuc5b^2p@T$#%(($$rU^$uY_C z$%)A+$?3^i$vMgS$qQx4i<9NaMafH&OOwl!E0b%IYm?U{pGtn3qM727l9;j}r8T8D zWmQUF%GW9VDSJ}(r5s2(oN_efc*@C?D=9ZqeoDEWazEwQlt(E~Qr@S0O65|Ar;bcD zOf^n5OSMe3NwrUPN*$LPk~%(hLh8iSh}5XmnAG^xNvU&Fn^SkC-b|B$G~=|uw5+tL zY17kYrOi%ToK}`rkye#flUAEnpVpPOB5hS#U)uV#4QZRxwxk_OJDPSO?QYtGwBOR6 zr2UchXWFZ@H)-$F)zUT6wbHfIb<%ayho$SMk4PVt?wy{T4%1hppGbd_!DU!vIA*wH zxMz4~1ZIS1NHQWbqBCMM;$<1qjQor#83h@I8FMn`XDrO9%&5+2&G2l zAdAh?&eF-!%^H@apJk9`k!71@pXHS0p5>Y4ljWBs$x6;j%gW5k&dSS@P0pH^wIJ)O zELql;tOHqxvyNq*%=$j-Y}TW!7g>L0z0GJ-PdG59GecQ_qu`=Goo|l-HktfZ|&6}JzGjDd@yu5{Zi}F_IUCbBc)A<_t2Kg5G_W4fv zuK6DMWAg*^gY(DdPsoqWkIzrZpPWB4e|G-7{Dt{N`AhQ4@+VSe{?9NUPL;t0unbnh8dwJvuo6d72PcQspxjm-J<(N zPm7)xy(s#tSWt`=6UA!9ql?EB8yA}vn-^OaTNm3EI~KbXyBB*FhZM`k7f&db6t5}X zQoOBrNAd0@+>)V7^p*@?GIB}vlGY{dOFEY`GF0m_dEO9AuFYzkzEtyyn zSrStcS2C$2xg@nDy(F__W=Vg^%~D~hS!rNtTIqt)veK5)_R_A>p3;@2Yf8T^U0=Gf z^g!vM(xas(N>7)bEj?d)vGj_p^jhiT(obbtWu|3LWm#o&%Sy@`%G%4i%6iIHmaQq< zSk_;*t!!u6p0d4Vx63}2i_0C#eak17N0!Hw$CoFTrx` z6_+cnRotw&U2(VKLB+$0XBE#YK2=hcbR}1*Ua3<#v{JuvMCGVTvr6kqkII0`pvut7 z36+w{gvzAK)XI!XX=P4jLFL>^S!H#lqO!TNwX&mfMdj+swUz5CzpdO;d9d(6O0CMMl2+wbO|F_+wV-NImAtCBsjfC`cw_7$!bwGTdh+)v|7K~pn6obVYN}UXLWM*{AyWgbwzb` zb!~M+bz}AF>i+6&)jO;ARPU=kP<^KQM)jTQd)2>IKdOFS{j&OX^}Fg1)gNm_HG^wL z*BI59)>zb7*Vxv0)%e!<*Nm$PsTp4rUz1pqQj=bjRg+z_sAhT1`kJFPCu&aDoUJ)u zbE)QP&5fF$YHruut$9%M+fsZfwUm}E<(8^1)m*B*RA;H~(qT*WmyTFEdg+*@u1h6L zvz9Ji+PZYh(jS&SUHY+BtJb8}w$`rJvDT~Bzc#owqBgQNrgm!Wg4#v3^4j9s(%SOc zb+ub-x7F^fJz9IJ_Dt=$+RL?9Yp>VdtbI|ZQ)gIbTxV8iS!Z2mTNhrJSeH_lUYAuT z%c;w&TU1wCS5sG4r>JYLYpq*dx4v#;U4PxSy6@`t*Bz`oQg^KGQr(@pm-V80&3c1+ zqk7YNi+byNr+U|V_j<2-pZW>)vGtkt`Snxlr`OM_Ur@iOURGaJzodRy{qp+t^~dW^ z)t{+9SAVhoO8xcvAM0<`|5AUy{$c&&`lk(ytbuD#Z_sKO+@RYqtUr#PrMqByQNsrX6pK=D}d zRPkK#vJo`Wja;L8qgLb4M*T*E#!-!ijaH4$jsA_HjT0IrjZux08j~AS8#5ZS8s{|1 zWR0+KX=6|0%EnENn;ZKZw>F+^{IT(IZbmtJxw>7ZZ&;s=9<-;HJi1Y&6=H?-I_g`y_@};CCyRI zvCRq1>CMxcXEe`hp3}Ufd42QY=4;JQmI-9b#LG;Vc`ox_=C{m$S=h3eWd+OTEUR0# zdfA3$*O&d=!nBB6bXtbC=(m`)*tR&dIJda9__p}B1hxdXgto-Cq_@m%sc30vX=-U{ zX>VECvajV}%aNA*t)SJo)wMOYHNSOEYh&xO*0$Ep*5$1$T35IBwSLpOzx7b-(bf~K zr(0!bTCcR;YW=14e(S^5$F0A&zH9y1CTPRkblZ&DOxw)ctlI3`eA>pg1-1pZN!pUz z(%LfGq;0d>!3Q!J3=~gJ7#ngcFgUV-%-?2)lt(? z+fm=4=xFNb?O4;Xwqsq#rjGuOtsUDtj&@w=xY}{OCUsA=Q}TTUhTZydAIXH=flp&oxgYf)rEC&U1PfJy4<_G zx_rB2{$1m`CU!-1MRmn=#dRfg&FyOJ+TQg;*No3{|7!+6)pe( diff --git a/Sources/Request/Request/Request.swift b/Sources/Request/Request/Request.swift index a19c203..5ef60aa 100644 --- a/Sources/Request/Request/Request.swift +++ b/Sources/Request/Request/Request.swift @@ -36,6 +36,9 @@ public class Request: BindableObject { private var onData: ((Data?) -> Void)? private var onString: ((String?) -> Void)? private var onJson: ((Json?) -> Void)? + //private var objectType: Decodable.Type? + private var objectDecoder: ((Data) throws -> Any?)? + private var onObject: ((Any?) -> Void)? private var onError: ((RequestError) -> Void)? public var response: Response = Response() { @@ -54,6 +57,15 @@ public class Request: BindableObject { self.response = Response() } + /// Initialize with support for the `onObject` response. + public convenience init(_ objectType: T.Type, @RequestBuilder builder: () -> RequestParam) { + self.init(builder: builder) + //self.objectType = objectType + self.objectDecoder = { data in + try JSONDecoder().decode(objectType, from: data) + } + } + internal init(params: CombinedParams) { self.params = params self.response = Response() @@ -83,6 +95,15 @@ public class Request: BindableObject { return self } + /// Sets the `onObject` callback to be run whenever `Data` is retrieved. + /// - Important: You must initialize the `Request` with the `init(_ objectType: T.Type, builder: () -> RequestParam) where T : Decodable` initializer. + public func onObject(_ callback: @escaping (T?) -> Void) -> Request { + self.onObject = { obj in + callback(obj as? T) + } + return self + } + /// Performs the `Request`, and calls the `onData`, `onString`, `onJson`, and `onError` callbacks when appropriate. public func call() { // Url @@ -155,6 +176,9 @@ public class Request: BindableObject { fatalError(error.localizedDescription) }*/ } + if self.onObject != nil && self.objectDecoder != nil { + self.onObject!(try? self.objectDecoder!(data!)) + } self.response.data = data } }.resume() diff --git a/Tests/RequestTests/RequestTests.swift b/Tests/RequestTests/RequestTests.swift index 7470271..d63fb97 100644 --- a/Tests/RequestTests/RequestTests.swift +++ b/Tests/RequestTests/RequestTests.swift @@ -61,6 +61,39 @@ final class RequestTests: XCTestCase { }) } + func testObject() { + struct Todo: Decodable { + let id: Int + let userId: Int + let title: String + let completed: Bool + } + + let expectation = self.expectation(description: #function) + var response: [Todo]? = nil + var error: Data? = nil + + _ = Request([Todo].self) { + Url("https://jsonplaceholder.typicode.com/todos") + } + .onError { err in + error = err.error + expectation.fulfill() + } + .onObject { (todos: [Todo]?) in + print(todos) + response = todos + expectation.fulfill() + } + .call() + waitForExpectations(timeout: 10000) + if error != nil { + XCTAssert(false) + } else if response != nil { + XCTAssert(true) + } + } + func testRequestGroup() { let expectation = self.expectation(description: #function) var loaded: Int = 0 @@ -115,6 +148,7 @@ final class RequestTests: XCTestCase { ("post", testPost), ("query", testQuery), ("complexRequest", testComplexRequest), + ("onObject", testObject), ("requestGroup", testRequestGroup), ("requestChain", testRequestChain), ] From ad74a629ed74a88b2bfe78c9eabf886857ed2104 Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Sun, 21 Jul 2019 15:58:30 -0400 Subject: [PATCH 02/25] Make generic --- .../xcschemes/xcschememanagement.plist | 9 +++- Sources/Request/Request/Request.swift | 47 ++++++++----------- Tests/RequestTests/RequestTests.swift | 2 +- 3 files changed, 27 insertions(+), 31 deletions(-) diff --git a/.swiftpm/xcode/xcuserdata/carson.xcuserdatad/xcschemes/xcschememanagement.plist b/.swiftpm/xcode/xcuserdata/carson.xcuserdatad/xcschemes/xcschememanagement.plist index 1df8b41..2f20246 100644 --- a/.swiftpm/xcode/xcuserdata/carson.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/.swiftpm/xcode/xcuserdata/carson.xcuserdatad/xcschemes/xcschememanagement.plist @@ -12,16 +12,21 @@ Request-Package.xcscheme_^#shared#^_ orderHint - 1 + 0 Request.xcscheme_^#shared#^_ orderHint - 0 + 1 SuppressBuildableAutocreation + Json + + primary + + Request primary diff --git a/Sources/Request/Request/Request.swift b/Sources/Request/Request/Request.swift index 5ef60aa..b0b9fe6 100644 --- a/Sources/Request/Request/Request.swift +++ b/Sources/Request/Request/Request.swift @@ -28,17 +28,20 @@ import Combine /// `Url`, `Method`, `Header`, `Query`, `Body` /// /// - Precondition: The `Request` body must contain **exactly one** `Url` -public class Request: BindableObject { - public var willChange = PassthroughSubject() +public typealias Request = AnyRequest + +/// Build a `Request` with a `ResponseType` for `BindableObject` +public class AnyRequest: BindableObject where ResponseType: Decodable { + private let responseType = ResponseType.Type.self + + public var willChange = PassthroughSubject() private var params: CombinedParams private var onData: ((Data?) -> Void)? private var onString: ((String?) -> Void)? private var onJson: ((Json?) -> Void)? - //private var objectType: Decodable.Type? - private var objectDecoder: ((Data) throws -> Any?)? - private var onObject: ((Any?) -> Void)? + private var onObject: ((ResponseType?) -> Void)? private var onError: ((RequestError) -> Void)? public var response: Response = Response() { @@ -57,50 +60,38 @@ public class Request: BindableObject { self.response = Response() } - /// Initialize with support for the `onObject` response. - public convenience init(_ objectType: T.Type, @RequestBuilder builder: () -> RequestParam) { - self.init(builder: builder) - //self.objectType = objectType - self.objectDecoder = { data in - try JSONDecoder().decode(objectType, from: data) - } - } - internal init(params: CombinedParams) { self.params = params self.response = Response() } /// Sets the `onData` callback to be run whenever `Data` is retrieved - public func onData(_ callback: @escaping (Data?) -> Void) -> Request { + public func onData(_ callback: @escaping (Data?) -> Void) -> Self { self.onData = callback return self } /// Sets the `onString` callback to be run whenever a `String` is retrieved - public func onString(_ callback: @escaping (String?) -> Void) -> Request { + public func onString(_ callback: @escaping (String?) -> Void) -> Self { self.onString = callback return self } /// Sets the `onData` callback to be run whenever `Json` is retrieved - public func onJson(_ callback: @escaping (Json?) -> Void) -> Request { + public func onJson(_ callback: @escaping (Json?) -> Void) -> Self { self.onJson = callback return self } - /// Handle any `RequestError`s thrown by the `Request` - public func onError(_ callback: @escaping (RequestError) -> Void) -> Request { - self.onError = callback + /// Sets the `onObject` callback to be run whenever `Data` is retrieved + public func onObject(_ callback: @escaping (ResponseType?) -> Void) -> Self { + self.onObject = callback return self } - /// Sets the `onObject` callback to be run whenever `Data` is retrieved. - /// - Important: You must initialize the `Request` with the `init(_ objectType: T.Type, builder: () -> RequestParam) where T : Decodable` initializer. - public func onObject(_ callback: @escaping (T?) -> Void) -> Request { - self.onObject = { obj in - callback(obj as? T) - } + /// Handle any `RequestError`s thrown by the `Request` + public func onError(_ callback: @escaping (RequestError) -> Void) -> Self { + self.onError = callback return self } @@ -176,8 +167,8 @@ public class Request: BindableObject { fatalError(error.localizedDescription) }*/ } - if self.onObject != nil && self.objectDecoder != nil { - self.onObject!(try? self.objectDecoder!(data!)) + if self.onObject != nil { + self.onObject!(try? JSONDecoder().decode(ResponseType.self, from: data!)) } self.response.data = data } diff --git a/Tests/RequestTests/RequestTests.swift b/Tests/RequestTests/RequestTests.swift index d63fb97..11f09cc 100644 --- a/Tests/RequestTests/RequestTests.swift +++ b/Tests/RequestTests/RequestTests.swift @@ -73,7 +73,7 @@ final class RequestTests: XCTestCase { var response: [Todo]? = nil var error: Data? = nil - _ = Request([Todo].self) { + _ = AnyRequest<[Todo]> { Url("https://jsonplaceholder.typicode.com/todos") } .onError { err in From f41d271957024afabdc8b2b07920fa3001cfc95f Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Sun, 21 Jul 2019 17:42:06 -0400 Subject: [PATCH 03/25] Codable support in RequestView --- .../UserInterfaceState.xcuserstate | Bin 50290 -> 49277 bytes .../SwiftUI/RequestView/RequestView.swift | 27 ++++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/.swiftpm/xcode/package.xcworkspace/xcuserdata/carsonkatri.xcuserdatad/UserInterfaceState.xcuserstate b/.swiftpm/xcode/package.xcworkspace/xcuserdata/carsonkatri.xcuserdatad/UserInterfaceState.xcuserstate index 8956bcf4dc51a2ae7f10280f4778f0cd8a8fc84f..6a170d71477e98a5e840a5a51ef9f2eea39a0a9c 100644 GIT binary patch delta 19373 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%0Dh-2<~{R<;d#?% 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 delta 20409 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 RXI$`4v`O(hc<=x7{{X^u$MpaJ diff --git a/Sources/Request/SwiftUI/RequestView/RequestView.swift b/Sources/Request/SwiftUI/RequestView/RequestView.swift index 38d78c7..89c173d 100644 --- a/Sources/Request/SwiftUI/RequestView/RequestView.swift +++ b/Sources/Request/SwiftUI/RequestView/RequestView.swift @@ -13,23 +13,34 @@ import SwiftUI /// `RequestView` is powered by a `Request`. It handles loading the data, and you can focus on building your app. /// /// It takes a `Request`, a placeholder and any content you want rendered. -public struct RequestView : View where Content: View, Placeholder: View { - private let request: Request - private let content: (Data?) -> TupleView<(Content, Placeholder)> +public typealias RequestView = AnyRequestView + +/// `RequestView`, but with Codable support. +public struct AnyRequestView : View where ResponseType: Decodable, Content: View, Placeholder: View { + private let request: AnyRequest + private let content: (ResponseType?) -> TupleView<(Content, Placeholder)> + @State private var object: ResponseType? = nil @State private var data: Data? = nil - public init(_ request: Request, @ViewBuilder content: @escaping (Data?) -> TupleView<(Content, Placeholder)>) { + public init(_ request: AnyRequest, @ViewBuilder content: @escaping (ResponseType?) -> TupleView<(Content, Placeholder)>) { self.request = request self.content = content } public var body: some View { - if data != nil { - return AnyView(content(data).value.0) + if object != nil { + return AnyView(content(object).value.0) + } else if data != nil { + return AnyView(content((data as! ResponseType)).value.0) } else { - let req = self.request.onData { data in - self.data = data + var req = self.request.onObject { object in + self.object = object + } + if ResponseType.self == Data.self { + req = self.request.onData { data in + self.data = data + } } req.call() return AnyView(content(nil).value.1) From f71cb6c1e33fa23ebe0a14ca4ccb96369fb7adc3 Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Sun, 21 Jul 2019 18:11:55 -0400 Subject: [PATCH 04/25] Improved Codable support for RequestView --- .../UserInterfaceState.xcuserstate | Bin 49277 -> 50422 bytes .../SwiftUI/RequestView/RequestView.swift | 38 +++++++++--------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.swiftpm/xcode/package.xcworkspace/xcuserdata/carsonkatri.xcuserdatad/UserInterfaceState.xcuserstate b/.swiftpm/xcode/package.xcworkspace/xcuserdata/carsonkatri.xcuserdatad/UserInterfaceState.xcuserstate index 6a170d71477e98a5e840a5a51ef9f2eea39a0a9c..57dcdebf7e012ec38532d576b4334fa74827f36a 100644 GIT binary patch delta 21628 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�lnAh- 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 CEl~mh delta 20136 zcmbW82UHYE+o-3zdZy!$1Vljv6v-fxa})u|If~@0h?v7n5hO_*1O$oZtgEZ8u31;t zoU^X3Y1dtITJx=DoK^qt`|mmTj;Gu1uBxu*4OR74b@93ie3XI)P4KJusO;HNL!e3w z*yMc)lZb%^&;$d4DKG=(zyer;QNRj}2G+nHxB*`<7WjcgkOanqWH14wfK-qM(m^(u z1g3)-U?!*s4WJP;0U2lp3qcEL1#Mt4SOV67wO}3i5o`rV!7*?goB$`mDR3H`0cXKQ za0A=~_rU}3M>hBbJ`(~0BX9x`1R*3u1WB-j8Zm%SCv=D*#86@wVMrJeE`%%LMz|9m zgeT!ecoRN^9}z-?5@AFf5lJ`taV0-?H4 zL#QbnDAW=T5)Kw>3w4CLLPMdE&{$|C94)jKjurX|{e=O-al$}hkT6&nB8(8m3loHC z!gOJVaJF!caISEkP$HBHp_#BmSSlP{r|@UtF5zzB z9^qc$KH(wZaoHX)TtbOdM5-b+k&(z)WFj&ZnTgCr79va0D3O)OR^%e`5seY~ih@NU zqBK#uC_|Jf$`WOZazweJJkcc4G|@bfL?jh8ix!GnM6IGW(IQd1s6(_^)FWCUS}9s3 z+9dixv|044=&0zJ=(y;F=%nbB=(OmJ=&b0X=!WQ?M08*DK=efPlq5(YDI!UdB59H# zS&}1F$bqC5sY~jS`lKCcPdbo}q!Z~(x{$7<8|g**lL6#7GJ=dGqsTlmpDZ9Jl9R|n zaxz&&P9clQ8Ki`il9gl?Sxq*PGI9mEl3YcuCfAT_$#vv- zd6m3IUMFvmH_6|~TjX8xFY*QXl6*zc6hpBTM~NvVN|{ojR4ENghZ;f|P$MZP%9(PZ zTq!roo${bODKE;G3ZjCk5Gs_4rQ)b~Y9cj>Dx@Y;Mbs3kn3_sWqh?W%Dxs>W8ft-r z>Y;k6K57ZIlv+kDr&draskPK*YA5wGwTn7Kou$rE=cx} zG)@DWpoO%ECTWVMX@*v!HRvJqPtqV^eEbfcA-7#F|p2{x`~$2&GbULh3=ty={|Z1y@vjg-b!zyx6?n-JLsMC zA^I2kFnxqROP{09(--L9=v(w1`UU-xenr2g-_Y;rPxNO7X8=PoVn&rwXY?2YW+Y?6 zm@<~kD8`HNW_*}2j4v~m@nig%0A@UsEMX=vDNHJp#-uYDOeRyzOl77q)0r8}Os0le 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 L|F1YNJ@9`36+9k& diff --git a/Sources/Request/SwiftUI/RequestView/RequestView.swift b/Sources/Request/SwiftUI/RequestView/RequestView.swift index 89c173d..9aa6923 100644 --- a/Sources/Request/SwiftUI/RequestView/RequestView.swift +++ b/Sources/Request/SwiftUI/RequestView/RequestView.swift @@ -13,34 +13,34 @@ import SwiftUI /// `RequestView` is powered by a `Request`. It handles loading the data, and you can focus on building your app. /// /// It takes a `Request`, a placeholder and any content you want rendered. -public typealias RequestView = AnyRequestView - -/// `RequestView`, but with Codable support. -public struct AnyRequestView : View where ResponseType: Decodable, Content: View, Placeholder: View { - private let request: AnyRequest - private let content: (ResponseType?) -> TupleView<(Content, Placeholder)> +public struct RequestView : View where Content: View, Placeholder: View { + private let request: Request + private let content: (Data?) -> TupleView<(Content, Placeholder)> - @State private var object: ResponseType? = nil @State private var data: Data? = nil - public init(_ request: AnyRequest, @ViewBuilder content: @escaping (ResponseType?) -> TupleView<(Content, Placeholder)>) { + public init(_ request: Request, @ViewBuilder content: @escaping (Data?) -> TupleView<(Content, Placeholder)>) { self.request = request self.content = content } + public init(_ type: ResponseType.Type, _ request: Request, @ViewBuilder content: @escaping (ResponseType?) -> TupleView<(Content, Placeholder)>) { + self.request = request + self.content = { data in + var object: ResponseType? = nil + if data != nil { + object = try? JSONDecoder().decode(type, from: data!) + } + return content(object) + } + } + public var body: some View { - if object != nil { - return AnyView(content(object).value.0) - } else if data != nil { - return AnyView(content((data as! ResponseType)).value.0) + if data != nil { + return AnyView(content(data).value.0) } else { - var req = self.request.onObject { object in - self.object = object - } - if ResponseType.self == Data.self { - req = self.request.onData { data in - self.data = data - } + let req = self.request.onData { data in + self.data = data } req.call() return AnyView(content(nil).value.1) From a3c8b0e72aa8873e2e4c82ba6eff5625e4fd891a Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Mon, 22 Jul 2019 17:33:24 -0400 Subject: [PATCH 05/25] RequestView updates on State change --- .../UserInterfaceState.xcuserstate | Bin 48884 -> 50945 bytes .../SwiftUI/RequestView/RequestView.swift | 19 +++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.swiftpm/xcode/package.xcworkspace/xcuserdata/carsonkatri.xcuserdatad/UserInterfaceState.xcuserstate b/.swiftpm/xcode/package.xcworkspace/xcuserdata/carsonkatri.xcuserdatad/UserInterfaceState.xcuserstate index 8e42e7fa7bb5ec29e24e8db24d794d811d51cd31..43a3465db5f62fb597de9bf4119ab4e0f372e977 100644 GIT binary patch delta 22675 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 Y=cSBsf>1p{rS*Qh+WYA$!K&{62b`b?82|tP diff --git a/Sources/Request/SwiftUI/RequestView/RequestView.swift b/Sources/Request/SwiftUI/RequestView/RequestView.swift index 38d78c7..7729d90 100644 --- a/Sources/Request/SwiftUI/RequestView/RequestView.swift +++ b/Sources/Request/SwiftUI/RequestView/RequestView.swift @@ -17,6 +17,7 @@ public struct RequestView : View where Content: View, Plac private let request: Request private let content: (Data?) -> TupleView<(Content, Placeholder)> + @State private var oldReq: Request? = nil @State private var data: Data? = nil public init(_ request: Request, @ViewBuilder content: @escaping (Data?) -> TupleView<(Content, Placeholder)>) { @@ -24,15 +25,27 @@ public struct RequestView : View where Content: View, Plac self.content = content } + public init(_ type: ResponseType.Type, _ request: Request, @ViewBuilder content: @escaping (ResponseType?) -> TupleView<(Content, Placeholder)>) { + self.request = request + self.content = { data in + var object: ResponseType? = nil + if data != nil { + object = try? JSONDecoder().decode(type, from: data!) + } + return content(object) + } + } + public var body: some View { - if data != nil { - return AnyView(content(data).value.0) - } else { + if data == nil || oldReq == nil || oldReq?.id != request.id { let req = self.request.onData { data in + self.oldReq = self.request self.data = data } req.call() return AnyView(content(nil).value.1) + } else { + return AnyView(content(data).value.0) } } } From 2e577f273beaacae3b224134b8914e815b189626 Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Sun, 28 Jul 2019 19:19:50 -0400 Subject: [PATCH 06/25] RequestImage --- .../UserInterfaceState.xcuserstate | Bin 50912 -> 54158 bytes .../xcschemes/xcschememanagement.plist | 4 +- .../SwiftUI/RequestImage/RequestImage.swift | 55 ++++++++++++++++++ Tests/RequestTests/RequestTests.swift | 1 - 4 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 Sources/Request/SwiftUI/RequestImage/RequestImage.swift diff --git a/.swiftpm/xcode/package.xcworkspace/xcuserdata/carsonkatri.xcuserdatad/UserInterfaceState.xcuserstate b/.swiftpm/xcode/package.xcworkspace/xcuserdata/carsonkatri.xcuserdatad/UserInterfaceState.xcuserstate index fbc3fb223822af7ad21b827c028ff90b29e45853..8af002b311a4e37a63d4c1db12140b96e51cbf0c 100644 GIT binary patch delta 23644 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%0D)5z%H5QHOu) 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 Km;0L1i2ngj`x{pP delta 21350 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 E0b+~O*#H0l diff --git a/.swiftpm/xcode/xcuserdata/carsonkatri.xcuserdatad/xcschemes/xcschememanagement.plist b/.swiftpm/xcode/xcuserdata/carsonkatri.xcuserdatad/xcschemes/xcschememanagement.plist index 2f20246..050b9c4 100644 --- a/.swiftpm/xcode/xcuserdata/carsonkatri.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/.swiftpm/xcode/xcuserdata/carsonkatri.xcuserdatad/xcschemes/xcschememanagement.plist @@ -12,12 +12,12 @@ Request-Package.xcscheme_^#shared#^_ orderHint - 0 + 1 Request.xcscheme_^#shared#^_ orderHint - 1 + 0 SuppressBuildableAutocreation diff --git a/Sources/Request/SwiftUI/RequestImage/RequestImage.swift b/Sources/Request/SwiftUI/RequestImage/RequestImage.swift new file mode 100644 index 0000000..4a51311 --- /dev/null +++ b/Sources/Request/SwiftUI/RequestImage/RequestImage.swift @@ -0,0 +1,55 @@ +// +// RequestImage.swift +// +// +// Created by Carson Katri on 7/28/19. +// + +import SwiftUI + +/// A view that asynchronously loads an image +/// +/// It automatically has animations to transition from a placeholder and the image. +/// +/// It takes a `Url` or `Request`, a placeholder, the `ContentMode` for displaying the image, and an `Animation` for switching +struct RequestImage: View { + let request: Request + let placeholder: Image + let animation: Animation + let contentMode: ContentMode + @State private var image: UIImage? = nil + + init(_ url: Url, placeholder: Image = Image(uiImage: UIImage()), contentMode: ContentMode = .fill, animation: Animation = .easeInOut) { + self.request = Request { + url + } + self.placeholder = placeholder + self.animation = animation + self.contentMode = contentMode + } + + init(_ request: Request, placeholder: Image = Image(uiImage: UIImage()), contentMode: ContentMode = .fill, animation: Animation = .easeInOut) { + self.request = request + self.placeholder = placeholder + self.animation = animation + self.contentMode = contentMode + } + + var body: some View { + if image != nil { + return Image(uiImage: image!) + .resizable() + .aspectRatio(contentMode: contentMode) + .animation(animation) + } else { + self.request.onData { data in + self.image = UIImage(data: data!) + } + .call() + return placeholder + .resizable() + .aspectRatio(contentMode: contentMode) + .animation(animation) + } + } +} diff --git a/Tests/RequestTests/RequestTests.swift b/Tests/RequestTests/RequestTests.swift index 11f09cc..1aaa9a6 100644 --- a/Tests/RequestTests/RequestTests.swift +++ b/Tests/RequestTests/RequestTests.swift @@ -81,7 +81,6 @@ final class RequestTests: XCTestCase { expectation.fulfill() } .onObject { (todos: [Todo]?) in - print(todos) response = todos expectation.fulfill() } From ad9592d2e84725e9fdfbaa7e8c40d9d5a17c64ca Mon Sep 17 00:00:00 2001 From: Carson Date: Sun, 28 Jul 2019 19:56:11 -0400 Subject: [PATCH 07/25] Initial `Codable` support (#4) * Initial codable support * Make generic * Codable support in RequestView * Improved Codable support for RequestView --- .gitignore | 8 +++++ .../UserInterfaceState.xcuserstate | Bin 50945 -> 50912 bytes .../xcschemes/xcschememanagement.plist | 9 +++-- Sources/Request/Request/Request.swift | 27 ++++++++++---- Tests/RequestTests/RequestTests.swift | 34 ++++++++++++++++++ 5 files changed, 70 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 78d01a9..8d2b6c0 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,11 @@ /.build /build /Packages + +xcuserdata +.build/ + +*.xccheckout +*.moved-aside +*.xcuserstate +*.xcscmblueprint \ No newline at end of file diff --git a/.swiftpm/xcode/package.xcworkspace/xcuserdata/carsonkatri.xcuserdatad/UserInterfaceState.xcuserstate b/.swiftpm/xcode/package.xcworkspace/xcuserdata/carsonkatri.xcuserdatad/UserInterfaceState.xcuserstate index 43a3465db5f62fb597de9bf4119ab4e0f372e977..fbc3fb223822af7ad21b827c028ff90b29e45853 100644 GIT binary patch delta 172 zcmZqdV}8)fydiWsqw40c<+V)Gcg@T#EUm0gnk+*>P1JQv=iF!>j6oXD}^eTE}#V=`7O~rsqtbnc0|ym^GMeaQY`&Um{J!|sA IWAco107P*w1^@s6 delta 205 zcmaFR%iP$>V7PoLyYq+&w(KJbirq`~w1m zf+xRQX(|!!7wlQ=omv^@7aZ#8=@J3r`X*-PP1agf$HLjb#5sA@s=DZTOlz37Fr8q! z%ygUS5z}j?f6QFWvdo&y_RL<)!OTg_Da>ii8O)i?S@h0MjwrOf5bmCV%) oV8Fx(p&3G;G?Zel+g!ccMw)ZZ>Upa-tlqkM_v8b|Request-Package.xcscheme_^#shared#^_ orderHint - 1 + 0 Request.xcscheme_^#shared#^_ orderHint - 0 + 1 SuppressBuildableAutocreation + Json + + primary + + Request primary diff --git a/Sources/Request/Request/Request.swift b/Sources/Request/Request/Request.swift index a19c203..b0b9fe6 100644 --- a/Sources/Request/Request/Request.swift +++ b/Sources/Request/Request/Request.swift @@ -28,14 +28,20 @@ import Combine /// `Url`, `Method`, `Header`, `Query`, `Body` /// /// - Precondition: The `Request` body must contain **exactly one** `Url` -public class Request: BindableObject { - public var willChange = PassthroughSubject() +public typealias Request = AnyRequest + +/// Build a `Request` with a `ResponseType` for `BindableObject` +public class AnyRequest: BindableObject where ResponseType: Decodable { + private let responseType = ResponseType.Type.self + + public var willChange = PassthroughSubject() private var params: CombinedParams private var onData: ((Data?) -> Void)? private var onString: ((String?) -> Void)? private var onJson: ((Json?) -> Void)? + private var onObject: ((ResponseType?) -> Void)? private var onError: ((RequestError) -> Void)? public var response: Response = Response() { @@ -60,25 +66,31 @@ public class Request: BindableObject { } /// Sets the `onData` callback to be run whenever `Data` is retrieved - public func onData(_ callback: @escaping (Data?) -> Void) -> Request { + public func onData(_ callback: @escaping (Data?) -> Void) -> Self { self.onData = callback return self } /// Sets the `onString` callback to be run whenever a `String` is retrieved - public func onString(_ callback: @escaping (String?) -> Void) -> Request { + public func onString(_ callback: @escaping (String?) -> Void) -> Self { self.onString = callback return self } /// Sets the `onData` callback to be run whenever `Json` is retrieved - public func onJson(_ callback: @escaping (Json?) -> Void) -> Request { + public func onJson(_ callback: @escaping (Json?) -> Void) -> Self { self.onJson = callback return self } + /// Sets the `onObject` callback to be run whenever `Data` is retrieved + public func onObject(_ callback: @escaping (ResponseType?) -> Void) -> Self { + self.onObject = callback + return self + } + /// Handle any `RequestError`s thrown by the `Request` - public func onError(_ callback: @escaping (RequestError) -> Void) -> Request { + public func onError(_ callback: @escaping (RequestError) -> Void) -> Self { self.onError = callback return self } @@ -155,6 +167,9 @@ public class Request: BindableObject { fatalError(error.localizedDescription) }*/ } + if self.onObject != nil { + self.onObject!(try? JSONDecoder().decode(ResponseType.self, from: data!)) + } self.response.data = data } }.resume() diff --git a/Tests/RequestTests/RequestTests.swift b/Tests/RequestTests/RequestTests.swift index 7470271..11f09cc 100644 --- a/Tests/RequestTests/RequestTests.swift +++ b/Tests/RequestTests/RequestTests.swift @@ -61,6 +61,39 @@ final class RequestTests: XCTestCase { }) } + func testObject() { + struct Todo: Decodable { + let id: Int + let userId: Int + let title: String + let completed: Bool + } + + let expectation = self.expectation(description: #function) + var response: [Todo]? = nil + var error: Data? = nil + + _ = AnyRequest<[Todo]> { + Url("https://jsonplaceholder.typicode.com/todos") + } + .onError { err in + error = err.error + expectation.fulfill() + } + .onObject { (todos: [Todo]?) in + print(todos) + response = todos + expectation.fulfill() + } + .call() + waitForExpectations(timeout: 10000) + if error != nil { + XCTAssert(false) + } else if response != nil { + XCTAssert(true) + } + } + func testRequestGroup() { let expectation = self.expectation(description: #function) var loaded: Int = 0 @@ -115,6 +148,7 @@ final class RequestTests: XCTestCase { ("post", testPost), ("query", testQuery), ("complexRequest", testComplexRequest), + ("onObject", testObject), ("requestGroup", testRequestGroup), ("requestChain", testRequestChain), ] From dd88227fcc2000d31d84b53b2daa75c7cf4532f1 Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Sun, 28 Jul 2019 21:21:30 -0400 Subject: [PATCH 08/25] v1.1.0 * Codable Support * RequestImage --- .../UserInterfaceState.xcuserstate | Bin 53494 -> 54027 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/.swiftpm/xcode/package.xcworkspace/xcuserdata/carsonkatri.xcuserdatad/UserInterfaceState.xcuserstate b/.swiftpm/xcode/package.xcworkspace/xcuserdata/carsonkatri.xcuserdatad/UserInterfaceState.xcuserstate index 748baed904f9c155ba0607f7b0d855cf36fbd8d5..86c22bf8c0d3b812aca0ec761ced7b289f467394 100644 GIT binary patch delta 14792 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 U))4uhTACmFhS9%c=N;Gn4^Wy~6aWAK delta 14295 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 Date: Sat, 3 Aug 2019 16:19:50 -0400 Subject: [PATCH 09/25] .gitignore fix --- .gitignore | 88 ++++++++++++++++-- .../UserInterfaceState.xcuserstate | Bin 53734 -> 0 bytes .../xcschemes/xcschememanagement.plist | 42 --------- .../xcschemes/xcschememanagement.plist | 42 --------- .../UserInterfaceState.xcuserstate | Bin 17764 -> 0 bytes 5 files changed, 79 insertions(+), 93 deletions(-) delete mode 100644 .swiftpm/xcode/package.xcworkspace/xcuserdata/carsonkatri.xcuserdatad/UserInterfaceState.xcuserstate delete mode 100644 .swiftpm/xcode/xcuserdata/carson.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 .swiftpm/xcode/xcuserdata/carsonkatri.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 Request.xcodeproj/project.xcworkspace/xcuserdata/carsonkatri.xcuserdatad/UserInterfaceState.xcuserstate diff --git a/.gitignore b/.gitignore index 8d2b6c0..2b5f284 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,82 @@ -.DS_Store -/.build -/build -/Packages +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore -xcuserdata -.build/ +## Build generated +build/ +DerivedData/ -*.xccheckout +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ + +## Other *.moved-aside -*.xcuserstate -*.xcscmblueprint \ No newline at end of file +*.xccheckout +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa +*.dSYM.zip +*.dSYM + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +# Package.pins +# Package.resolved +.build/ + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ +# +# Add this line if you want to avoid checking in source code from the Xcode workspace +# *.xcworkspace + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# Accio dependency management +Dependencies/ +.accio/ + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output + +# Code Injection +# +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ \ No newline at end of file diff --git a/.swiftpm/xcode/package.xcworkspace/xcuserdata/carsonkatri.xcuserdatad/UserInterfaceState.xcuserstate b/.swiftpm/xcode/package.xcworkspace/xcuserdata/carsonkatri.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100644 index 75f04c58f47d5c026def02a51029f4c3fd09d422..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53734 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 - - - - SchemeUserState - - Json.xcscheme_^#shared#^_ - - orderHint - 2 - - Request-Package.xcscheme_^#shared#^_ - - orderHint - 0 - - Request.xcscheme_^#shared#^_ - - orderHint - 1 - - - SuppressBuildableAutocreation - - Json - - primary - - - Request - - primary - - - RequestTests - - primary - - - - - diff --git a/.swiftpm/xcode/xcuserdata/carsonkatri.xcuserdatad/xcschemes/xcschememanagement.plist b/.swiftpm/xcode/xcuserdata/carsonkatri.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 2f20246..0000000 --- a/.swiftpm/xcode/xcuserdata/carsonkatri.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,42 +0,0 @@ - - - - - SchemeUserState - - Json.xcscheme_^#shared#^_ - - orderHint - 2 - - Request-Package.xcscheme_^#shared#^_ - - orderHint - 0 - - Request.xcscheme_^#shared#^_ - - orderHint - 1 - - - SuppressBuildableAutocreation - - Json - - primary - - - Request - - primary - - - RequestTests - - primary - - - - - diff --git a/Request.xcodeproj/project.xcworkspace/xcuserdata/carsonkatri.xcuserdatad/UserInterfaceState.xcuserstate b/Request.xcodeproj/project.xcworkspace/xcuserdata/carsonkatri.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100644 index a93e32cfda88f4f93a51473515877ec39e40c15d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17764 zcmb_@cYIS-`}jHcW;98gCTZG0=}4Ni%uYI?g>ERLlumX@)3gn3lai!BnWu;-Ly;jv z5NR1QL==@J$PmSWs7wbSLj(jBWvQV2o^x-~0le?`{o~hs(wuwGdd~Aa=b7h})zw%W z&Zwx92qOluNPvV$#2#l)3^PnH+Z`60b(q0cHqLBvI))pJc2kuFUKbjiwmKEUv)61> zVt*t?9>@o&kuU0ux}dJ88|sdFpl}p{B2fm)L|G^s^+Wwp4jO<4qCuz_m7rm0II2Wd z$b!b9YE*;l$blNrWHbvsi)N$e(2M9Lv=psEucFoHE%Y|pj^07=j9iEJ*;Hh{vehxp6=inFdBD@r@!A*EQ-h$u2 zZ{h9u9lRUw!5`p5_+xw=pTH;aDf}%yhkwDh@qPRNKg9nqm=QBlM#lIuevF3czyvTM zjGpPv^kBl72quz=W#X75rWezj>C0p=nM@utl*wlbm_lYOV`R!06I0GqGPQU_si+Pb*z$|8#FmbE;5&x z%gm3=73L@AXXbb259V*?0rQY~#3EM2Dp)n!k@aUoSUqcCyRqHb9&9?B!Dg~qY&P4E z?a$`01K5G=Aa*dD%MM}l*rDu5b`(3B9m7_zb?kW7&N^5pThC5l3ERldWS?PQU|(bx zurIN%uq)YB>}%{c_AT~pc02nHyOZ6+zR&Ju53nDzpRr#Q8Lag+H7Ae+Ns$bBB5$NB z$t{SeHa9p%z^{wriVdb3qr=gRypWtQgl$F&q$C2en{+Ex7~-;GW1=#m(!&$dqhi8i z<6@J-6O&@%!qcO(;xaQb(_)gM(n=NToXo5eo4wjmXEd2JZKnEKv(@RI*bfDvu-B0W zbwC}FKk9@6P#_T!5fKv)A|X;DdmRNMEz+S7XktJ*;z_(nIN1qJ{NT6i7&^MeT5g+| zZ8z4MOBH?EPFH9w%dlCUc3Vx2* znVE?R@uiBemJy+My3t-@bQD`0ma-aiiN#q}V6j%#n4zXr(WUK7JPf6|1^H%&(`Gk9 z^8%;QY0fk{jiriUXqskn!q#oUM0?N_9b0F$*=ov+_8j-DrHT%%bsR)(sya@Y5)&WW zLmM3(HLZtsN_1>gR1a-ZeAKjQZVX4EBoww0MWYzh6UCx96ps>6B9Rksq9975B0fY- zd^ZAad!uBOg8HDoP)-BvYDg-{B>hMZl#5B%QiTHGD5$bc%r#E1R2pHG{HvD7G`ktr zN?YYv9d#hFY|EzM0Yf6cG^@Gt+6t))Sq9G`cbRZpx|5}s}kA^Om1d(8(U5|{Y47j=+I9f-#11CpNZsvDO)}%V4wcK2u<22Vg z3hid#YHt9~4GI4y2;O8HEj8wH3aBI7QsXq+fjP6Rl=sT%zHqT^KEPkfF<61A%3N!H zyr~=7T4Y12CS)ZcO{k9O=@zHc78`5o&5kq<5O-52nt;NZP(3j;p@}4vbRCs%9uKXY z94ziuQ_u{G{HbUfnohz(g$4*DO^lCg-D9tz*Qpd6gPMTWYtcHO z_XePH6wo`G!~o5EzK%8mwKv08hqj_ONi0x14!+?ene?G_51<6j7))hG{S(A2Rp_7^ z=m?V2EkPfrA}^0J8vs`p6BT;Uwx8WrUkCCl1LU8v&S5T3ZzytrAmnyi3q!YKw{&xb z&ECo)Jg@PK=OoONi{F8EwV-h~iEl;YUi1M)<35tmg!Yp}(zV3JByK!^h(1AK>wqCX zLLZ|efaoOBi}a>1+HwitzofucZ#S78MI5V?49dyK$}Pxp4|5!yYysdDNofV(8}wZZ z0303NJe$7J=<=pZ4suf zp)tY?ECplIzX=&Yq{EP%S~|K!1r@IRmT|bdiLr!s^B@D7u#^m>-ISTdg)Op}6H?rY zu^io6i@mV|E6E@-loXH*_aJKA0jbtvU+jl9WH8AkL)L;mGT=_2h5Se!={6dM%qa(! zwNzL@H_)e6{ilFO3fW*|rPboBFE{H`$0P2~J$?uddt&@V7{4p=h4J%AH+||nZMz=f zIQsD(m_igw3ZX|46@FBawdfbBfApz!sqF?y!u?R#R@@8s#>qGZ_rZN}Do(@cI0I+m zESybB$S^XTj36V)C^DLiA*Ez2F_JQ3+KT(*96SII#Dl0+gNMNLP@InofZpZAOe%<# z*Z`1lG9I4oWI9<3Wx#z5zd;8ZCs}GOlg$~n+B&1%0#bA^D6vwyyIrK@l_B?5p>;jf z*ElV8V3<%nnrFAvg4`TrY_Qc+J?B=%ErcD>ZUndTY1Oe@!yM34lk$wtDyn}eH}Um= zJo?}sleYr2ndS;3fRIPs8V8k6`Q|#i*#QM3mEw*u?p2j@rcvX zjp43#SqNNbswMy=*OVL}JQQ92D*`Q!78n$$RH1UAXOOwVS!m0*R93kyS6qRsTK0v7 zRFbaz9;iXLnsF_*k}6W&%KzhW{S(|a0k~}vu>g_Bk#55QR(=`!RLj_QOg0TSKGAn3 zu*@t{11wSNR?}^9txp|wfEz=BPT;wC9+Kht;9R``WX>&UA=x0awbEGyq-yhyQ}zl> z>NvTD7vPshwyAB#3(*U0U%2<*V!VWxo2T$Hyd0)mfnUKZ@hbc(UX5RaDco9Xkj=!= zdQ9tPr`*G}s5M%wt*@!YLYZqwg}ZNS9hpp=WEydhhEhdji!sJ4G_VS&NXoR);UZe3 zV2f?Wlc^c6Yr<#tX2WF+17j!2Wy4q~9%=(JlR!Dg<82ti~9_b#$DEibPi zvNX?Vsy0@d9g&WSmI`OMoj2JcU0OL}619Wt?6z_IGT+C0VGn`mb>rVnyJozPuI_17 ze9!&(0B?=7qev?z+Hc@ye2@-Dy{Z4HJx{<7(XA$Yn9OM1V@L2&q*{kR!Jp#Ka0(%$ zk<26`)&W_M;V*H2pyM;78UBN0R~Pe<6@JGR)R)y#;i>T9pZkMw0*wx01oZ1j%1i?- z*7AYo27cz#bmlW;7U*{T9nk7~d=^|ZQ$1J%R%g2rXjk$qY5E4A$3Nf;_#(8vgfHVC z@fG|NzKXBm>rlFZZvwBoDcueQxtvF4M*m*-Cs}N1w6l>U>GE0SiFl7;vFp=JMTpmH$9NZ$8{9-&A1;|*&i;*+l z9G7qS_znT(^R(t*G)}PC>K%nfd!^aM zDj77s0zrqTj9$vWYulQ`CDRdb$@r5cWYS3{5M%{N3?_&P#yc3@a0dqxXj8J3ybPFI zsZTptd#WmC^@r}Y8ko*tVltsj7+FS^H#1$Bu4Dyyg>)_E7gfwp2+Hrt`3tGP#-lij zi7r(HwgdZdG^}M}n4T2<|GnAMMafg=cdsFyN#ONOsUm>`A)*~11@(1xHoG%|UyvKD z_HEk9bS9Zearxd{48bJ==mu_P`p_lNDAp63o5w^d15qyD$Ll%q(afaN&QGtT?zKy} zl=4HnmzTv10LO^QX8JMxnH;i?tS1}D>+6_-%phhklS?*|H_2P%ZPIlZHB6{!Je;#l zXlVp*vhaoW+ZdO)LPZEKk^&oXnK=+O^)%m;e; zksY+hiVL*=#|1pbip5lfS@)yHW9v2QQD-K7;O}MV&dYX;7xRbwg`fhy%GU!Pw0Kv za=-v`lm#x>)pqXY#7^+KcXGSXT66DC zW1=P{RG6cBnv7*8V?`85v)lqOlFa42p=Y+AOHE79fFNbR{y75%4jP<0ByVVbL19sG z$*|$0-BWM?18E8^&Ki&vN}xPHHy=hf+aVbN(cpCI)fR(B&!MaX4okMh?g01EQD*}m z!475sr$>2vNzpP0k30ud7dRVg%!7@NYEU-rDOwmkCzGG0pS><86Zi%u%qgGLf`;7s z+A_19V8RlS2V_CSL_nkpZ%9+9AsaI48A!e6)`y@XG!a6c3(*Gj1;mqX zqTA>pq{4i$26u!+SQw6mh`~rmdsSj9o`4(iGx%9Zbj`u@AkDQE5?Y5LrS%CIQV$`4 zrC@v*eI_PTJ_9IRzAqMlmXoTz6^}~KbcJaDx3G*`0${lS5 z!L^oI!YoBE04=CR>K3%inPwEWiCMwC!mMOgF|RVKnb(*#OcU8d-Y0v>KJo$CPY#fS zFeS(@6&u~yiixjSCc z(!2v7zU5(d4@NK%NDG^367JHQ;Gs`4QDxQY3Yd;&quRuh`}gfo|qlq&N6e|eEvX_-n5H z35h4>DDwp{>6gq`%-76u<^=had`3PeN68oD82OTXwUIeR17JwUe2e?T|Fh(4;0GEQ zKLOT9I5|nz@87yOe(@14W-fTyPgX+cX|Tl#@vS-t*FLqH;wi%hnRM`nL1jL*O^$T} zpZ5b|>z{04qFF_b`66r;6%I2n$y4TP)2hZ|g}I&%Zd$#w%0^A0C#$Ju%eK{&gA(Em zqN~*WzebLeN&NE-ypDRg+y`*Re*cgZPox|zAp{7KG`Z%DVI z3K-onrrZ^4;KM@v(Eo6@m$C!n8id6xOD(D!WPTGXAm6nF%2_chgIrHL4~q3Z-L|beI0MV) zUvpa62|h05BU@hb<7PvOs0Ko3zHJAfc5@Bg7Eb^H#vGVLPN?v))K%H6kdLjc2cO$! zkM0=}l?N&J@(Ipz4&v~~8uaR!046{@7)IIAS!v<1(McKMY1tVW;XUIMViVF6q7q|b zV~Qsw#+Sy&7F+V@;3N2-=;$6XZsg~)#lTx^0b9rxk-Ov`xxbbzVTZB9$)Al_-H2Jr z3Q<7G_Cnhw;K3IzsIR55Zl1^m=1MB80jD&t-oDF_IxY|mD0rfZvrxEQ!Iq+1>)Ela zku76QY&rR>5u-*dXv7|k*t5l-U@O^b3Uw8z<8kC~@_;;C%hs^9td;yj{w0qn%=D;1 zdjQ&j2qAi#9duBsqWgbum=2Mu0y886_@sQ-|K6IPgY(_=sUEzTFd=OygS2j^*p2y# z?35?gFqNIg4sXO@w=f*)^{FmNGgMoYUT>*!D*$#D`}`A~=dg3xd5u`uh((Q9OuFh* z6@2gfURuza|6%tnWM6(_q^0aKc6lR~G-7EZmcdAUc~=X$mcqGQ?5oV8AxgjJ9&@!C zXa29QmQL*9t?=&@5Z1XnI9Z9hq!iAc9a2y{Vsxd|K4J1S*FhTIAp_&lgd4K{O{ z6a0s=dN5JIbkq`dctO3%WHy7hazd$+`uKHxieu8O_9X%$Y}RyuV=n&07p$#p$ml{# z$mH7Wrvih5wNhP(-Vh2k)DeMsE3#{hl@4m8w|Lf2NoAWpHH^ox@_7ZEsu7cpV_0B;(iI|H{`@Sh{o8=vfk-I0J)&aQhDSuwb2-FwZFEdeIE+J2l4v;3 zDWi}=S(H=c0Ik~6nX|ZQ1qHOtTP>`H>yT}RoVVRvV0MCqR_SQd#G7wGVdTa|;K$o0p#pgyPCDVqp=tezyhP5};jMI4BpYONR08 z44|hK@6E$=pYj%3j~wOVgyxaCr^b|yHA>4&<>m^QuB6K1Gy|Me=7A6e@y0y>vlP%{ zSD*l(t{&prwHya=FVmw?2E+suES!Z2K3QcMC#|mOS6c}Ao=gay=452RxSUo{NZ=qt z&~clzZalnl#V?dq2q~**OqBuds)a*V{qoa>4;wy0D?SSzkp@nbMIdjZ$x#Q%he4D9 ztpFI$h;9GhI}HaP;qOE^9jk54|4kDh420hZfPYrGF_V@Pp}gH>%qnn|f1Y3|&V_O+LQF`VGd&;51E5@1 zUtN?2y zDCg$l`_WbMuw?+uRyYQ1~1U=!~TQEqFB8cKCO6|t{`Fnz>XyDZG-u2P zfQ*MiJJVijF@3q<)_jITrYDfi=20fafd|_lDA<20oN7Pr}(sGk%=MM!+mLFXh=Z zZWPL4weY2sHFI?B2lE?&9uB~EJ@6^zjd0+YwzT7CX|n^4Ox@c7X;05T@F~*1q1gQi zHw)!7?J2>oQ71f)Os%lK%pOs1Mcs^A7xhNe?Wpsu zEuzju{StL5stIatu!|vDwGX0Id)T8$3r~9>Vzrwqy#dFU_p)!d^lQ)I{61>W;gsJ@ zE{>*abh>z|E$_EkA%`zFwrG1drN+5-YFpl;_-)HElw$uIL~SYBULx?+;dY%|FOQas z<=y0Q@-#V?>);b3Plb|R9wHwk*FbH5d1ra1yi*H4_&rYHp!=P2m|HHiO0nTk>*fTy zzAE4YJ14V@uJt~?Ms2%QQi*11yQ{Dl>`ZCm^`8D>#0QD;$>s53VnX#sJ|#1X+_cWy(m&N0Ln?U zl@n}i&^IW=!Xk((HLAz0#iMB!L_E63i!hT2LIKc$|oq+xb zkreDHHR=djRS(*lk2LoNotXtTzz|djmpR73I;wz@cEIdZ)CiY2=D`(?m(eTeH8_#F z3B3tdICi4F=pY=n{2VTCoI>A&KDmN!pj+r3dVnz&b5}Mx!i9}c+#ScjRgFGyifs@a zOB)UsG-$NC9xi1(!^Npz!A*D*ej6@f9E1ZGU&Gali*TCZ5BxX7LN;B^1TtZ8!6K1K zgQR64Ga9Z@jEC4Yy*>f4V&)CFEOC(eoH+&2>l@5nxDFv>{a76v&L*-MaMfW1TyU_n z)4^F>$~Hq3dk=erJ;7dJZ?b<0L;@dyRuB$U>@O%1m;~bm(*^SduLw2@b_fm&P6#dv zZVCPsdIaq{( zqxZ@1G5I{>v(D!upDSvSy0bb*Jx)DOy;Xfoealzn8|z!_JIQyY?>^rPeym@ZUyfgm z-vYnwey9EZ)&y$OG-k~l&6}Fzn)@9(bx7@C?l8B*whpH{{M}L8F{@*B$Auktc0A`V z@bBh7)PJJ?YX6V?Z+235>fOoIX>OZeUPgzreb{6@ecH z-VE{!N(~wpv?S<*pzFat!F_@)!ApYo2mh?~)uw4{w9B=JwYPKuy8gO)U6byZ?m81KaeT9CB{*eBbA=oh3Fx9Zd@Li}RG%>U)bXn+;(EDMX!%D)Q3)>lX zt#gOYIh`kW-qQJO7q2dTyNvJB+~s6fQP;$-)m>lh`c*fkTU@uQZY#Te*`4Vg-`&#v z)$U*S5cWvwVeQe}<4m|`cv|>`@GapNBm5!;Ma+!Y8S!hRA#z0I!pI|$|3<|{)qr;U zK3Ww$AbMu>p6EYfy2Y4cR>qv{>D4p4=Zv1adj1~UJ=Pq%I`*45pSZzs&&3^z`zJmj z-X8yE{PhGw!q|jW31<@3iFt|h6F*53CZ#9MNZOn9SFiY9&R*Ml{nk6YcXjX0y{{#A zPBtg6OTL^El44A0O1aQS+h=T_HGMAh)%7*@ZSH$1Ri9d(x*_#yTGzC3X>X+cnjV#I zPk%4{enzj1X&DDH+01^Kb2E=+sj`Z)UdcM29g_4#o!v1G+ z0&`3`n{sXqNEk3}z~Oki|pJ z<#o;*pZESy(a^l1D~JA+ADurn|44yPL21F}f_sJOg$oM5FX~cMUv#M0yLeRbrsDf0 znI(%#E)0ttHf`AF!~KU_hVL379#K4E!-%^hvqru=^2(^VQL{ ^HBLq|u*_@gGw& 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 NvZvdbT_|Pw{{xl}iB$jq From 8aa6735f0fec6d1c6e1a12b6b3d7a2fbaa916d2c Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Sat, 3 Aug 2019 16:23:48 -0400 Subject: [PATCH 10/25] codecov --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6110b7c..8f56a74 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,6 @@ os: osx osx_image: xcode11 script: - - xcodebuild clean test -project Request.xcodeproj -scheme "Request-Package" -destination "OS=13.0,name=iPhone XS" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO ONLY_ACTIVE_ARCH=NO -quiet \ No newline at end of file + - xcodebuild clean test -project Request.xcodeproj -scheme "Request-Package" -destination "OS=13.0,name=iPhone XS" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO ONLY_ACTIVE_ARCH=NO -quiet +after_success: + - bash <(curl -s https://codecov.io/bash) -t aea9733f-4e7d-420d-9c8b-04fe78c1e7aa From 78542621c9294a57d7f74cdf0bfaa2b953360afb Mon Sep 17 00:00:00 2001 From: Carson Date: Thu, 8 Aug 2019 21:27:43 -0400 Subject: [PATCH 11/25] Improved `Json` Implementation (#9) `JsonBuilder` was removed in favor of `ExpressibleByDictionaryLiteral`, as well as other literals: ```swift let json: Json = ["key": "value"] let json: Json = ["Hello", "World"] let json: Json = "Hello, world!" let json: Json = 5 let json: Json = 9.41 ``` `@dynamicMemberLookup` allows subscripting to be more expressive: ```swift // Instead of: myJson["key"][0]["key2"] // We can do: myJson.key[0].key2 ``` You can also use the lookup to set values: ```swift myJson.key[0].key2 = 5 myJson.key = ["Hello", "World"] ``` --- .../xcshareddata/WorkspaceSettings.xcsettings | 8 + ...3400B6A4-B231-4550-9C4C-2D5F1474250B.plist | 42 ++ .../RequestTests.xcbaseline/Info.plist | 33 ++ .../xcshareddata/xcschemes/Json.xcscheme | 67 +++ .../xcschemes/Request-Package.xcscheme | 106 +++++ .../xcshareddata/xcschemes/Request.xcscheme | 67 +++ .travis.yml | 7 +- README.md | 36 +- Request.xcodeproj/project.pbxproj | 431 +++++++++--------- .../xcschemes/Request-Package.xcscheme | 119 ++--- Resources/planned-features.md | 1 - Resources/swiftui.md | 10 + Sources/Json/Json.swift | 240 ++++++---- Sources/Json/JsonBuilder.swift | 8 +- Sources/Json/JsonProperty.swift | 61 --- Sources/Json/JsonSubscript.swift | 29 ++ Sources/Json/Literals.swift | 50 ++ .../Request/Request/Extra/RequestChain.swift | 4 +- Sources/Request/Request/Request.swift | 40 +- .../SwiftUI/RequestImage/RequestImage.swift | 4 +- Tests/RequestTests/JsonTests.swift | 161 ++++--- Tests/RequestTests/RequestTests.swift | 6 +- 22 files changed, 967 insertions(+), 563 deletions(-) create mode 100644 .swiftpm/xcode/package.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 .swiftpm/xcode/xcshareddata/xcbaselines/RequestTests.xcbaseline/3400B6A4-B231-4550-9C4C-2D5F1474250B.plist create mode 100644 .swiftpm/xcode/xcshareddata/xcbaselines/RequestTests.xcbaseline/Info.plist create mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/Json.xcscheme create mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/Request-Package.xcscheme create mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/Request.xcscheme delete mode 100644 Sources/Json/JsonProperty.swift create mode 100644 Sources/Json/JsonSubscript.swift create mode 100644 Sources/Json/Literals.swift diff --git a/.swiftpm/xcode/package.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/.swiftpm/xcode/package.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..54782e3 --- /dev/null +++ b/.swiftpm/xcode/package.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + diff --git a/.swiftpm/xcode/xcshareddata/xcbaselines/RequestTests.xcbaseline/3400B6A4-B231-4550-9C4C-2D5F1474250B.plist b/.swiftpm/xcode/xcshareddata/xcbaselines/RequestTests.xcbaseline/3400B6A4-B231-4550-9C4C-2D5F1474250B.plist new file mode 100644 index 0000000..ad4cc62 --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcbaselines/RequestTests.xcbaseline/3400B6A4-B231-4550-9C4C-2D5F1474250B.plist @@ -0,0 +1,42 @@ + + + + + classNames + + JsonTests + + testBuilderPerformance() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.0003 + baselineIntegrationDisplayName + Local Baseline + + + testMeasureBuilder() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 6.633e-05 + baselineIntegrationDisplayName + Local Baseline + + + testMeasureParse() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 9.35e-05 + baselineIntegrationDisplayName + Local Baseline + + + + + + diff --git a/.swiftpm/xcode/xcshareddata/xcbaselines/RequestTests.xcbaseline/Info.plist b/.swiftpm/xcode/xcshareddata/xcbaselines/RequestTests.xcbaseline/Info.plist new file mode 100644 index 0000000..3b43d51 --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcbaselines/RequestTests.xcbaseline/Info.plist @@ -0,0 +1,33 @@ + + + + + runDestinationsByUUID + + 3400B6A4-B231-4550-9C4C-2D5F1474250B + + localComputer + + busSpeedInMHz + 400 + cpuCount + 1 + cpuKind + Intel Core i5 + cpuSpeedInMHz + 2300 + logicalCPUCoresPerPackage + 8 + modelCode + MacBookPro15,2 + physicalCPUCoresPerPackage + 4 + platformIdentifier + com.apple.platform.macosx + + targetArchitecture + x86_64h + + + + diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Json.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Json.xcscheme new file mode 100644 index 0000000..2765ce0 --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/Json.xcscheme @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Request-Package.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Request-Package.xcscheme new file mode 100644 index 0000000..3aaeb57 --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/Request-Package.xcscheme @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Request.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Request.xcscheme new file mode 100644 index 0000000..f3a3fe3 --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/Request.xcscheme @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.travis.yml b/.travis.yml index 8f56a74..c462ed9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,9 @@ os: osx osx_image: xcode11 +language: + - swift script: - - xcodebuild clean test -project Request.xcodeproj -scheme "Request-Package" -destination "OS=13.0,name=iPhone XS" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO ONLY_ACTIVE_ARCH=NO -quiet + - swift package generate-xcodeproj + - xcodebuild clean test -project Request.xcodeproj -scheme "Request-Package" -destination "OS=13.0,name=iPhone XS" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO ONLY_ACTIVE_ARCH=NO -quiet -enableCodeCoverage YES -derivedDataPath .build/derivedData after_success: - - bash <(curl -s https://codecov.io/bash) -t aea9733f-4e7d-420d-9c8b-04fe78c1e7aa + - bash <(curl -s https://codecov.io/bash) -D .build/derivedData diff --git a/README.md b/README.md index ebed088..768b447 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ ![macOS](https://img.shields.io/badge/os-macOS-green.svg) ![tvOS](https://img.shields.io/badge/os-tvOS-green.svg) ![build status](https://api.travis-ci.com/carson-katri/swift-request.svg) +![codecov]() [Installation](#installation) - [Getting Started](#getting-started) - [Building a Request](#building-a-request) - [Codable](#codable) - [How it Works](#how-it-works) - [Request Groups](#request-groups) - [Request Chains](#request-chains) - [Json](#json) - [Contributing](#contributing) - [License](#license) @@ -54,11 +55,11 @@ Request { Url("https://jsonplaceholder.typicode.com/posts") Method(.post) Header.ContentType(.json) - Body(Json { - JsonProperty(key: "title", value: "foo") - JsonProperty(key: "body", value: "bar") - JsonProperty(key: "usedId", value: 1) - }.string) + Body(Json([ + "title": "foo", + "body": "bar", + "usedId": 1 + ]).stringified) } ``` Once you've built your `Request`, you can specify the response handlers you want to use. @@ -111,9 +112,7 @@ Sets the request body ```swift Body(["key": "value"]) Body("myBodyContent") -Body(Json { - JsonProperty(key: "firstName", value: "Carson") -}.string) +Body(myJson) ``` - `RequestParam` @@ -188,7 +187,7 @@ RequestChain { Url("https://jsonplaceholder.typicode.com/todos") } Request.chained { (data, errors) in - let json = Json.Parse(data[0]!) + let json = Json(data[0]!) return Url("https://jsonplaceholder.typicode.com/todos/\(json?[0]["id"].int ?? 0)") } } @@ -203,23 +202,22 @@ RequestChain { You can create `Json` by parsing a `String` or `Data`: ```swift -Json.Parse("{\"firstName\":\"Carson\"}") -Json.Parse("{\"firstName\":\"Carson\"}".data(using: .utf8)) -``` -Or you can build `Json` by hand: -```swift -Json { - JsonProperty(key: "firstName", value: "Carson") -} +Json("{\"firstName\":\"Carson\"}") +Json("{\"firstName\":\"Carson\"}".data(using: .utf8)) ``` You can subscript `Json` as you would expect: ```swift myJson["firstName"].string // "Carson" myComplexJson[0]["nestedJson"]["id"].int ``` +It also supports `dynamicMemberLookup`, so you can subscript it like so: +```swift +myJson.firstName.string // "Carson" +myComplexJson[0].nestedJson.id.int +``` -You can use `.string`, `.int`, `.double`, `.bool`, `.json` and `.property` to retrieve `JsonProperty` values in a desired type. -> **Note:** These return *non-optional* values. If you want to check for `nil`, you must cast the `.value` yourself. +You can use `.string`, `.int`, `.double`, `.bool`, and `.array` to retrieve values in a desired type. +> **Note:** These return **non-optional** values. If you want to check for `nil`, you can use `.stringOptional`, `.intOptional`, etc. ## Contributing See [CONTRIBUTING](CONTRIBUTING.md) diff --git a/Request.xcodeproj/project.pbxproj b/Request.xcodeproj/project.pbxproj index 9f2b4a1..d60f315 100644 --- a/Request.xcodeproj/project.pbxproj +++ b/Request.xcodeproj/project.pbxproj @@ -17,7 +17,7 @@ "en" ); mainGroup = "OBJ_5"; - productRefGroup = "OBJ_44"; + productRefGroup = "OBJ_45"; projectDirPath = "."; targets = ( "Request::Json", @@ -33,15 +33,19 @@ sourceTree = ""; }; "OBJ_100" = { + isa = "PBXTargetDependency"; + target = "Request::RequestTests"; + }; + "OBJ_102" = { isa = "XCConfigurationList"; buildConfigurations = ( - "OBJ_101", - "OBJ_102" + "OBJ_103", + "OBJ_104" ); defaultConfigurationIsVisible = "0"; defaultConfigurationName = "Release"; }; - "OBJ_101" = { + "OBJ_103" = { isa = "XCBuildConfiguration"; buildSettings = { CLANG_ENABLE_MODULES = "YES"; @@ -80,7 +84,7 @@ }; name = "Debug"; }; - "OBJ_102" = { + "OBJ_104" = { isa = "XCBuildConfiguration"; buildSettings = { CLANG_ENABLE_MODULES = "YES"; @@ -119,51 +123,57 @@ }; name = "Release"; }; - "OBJ_103" = { + "OBJ_105" = { isa = "PBXSourcesBuildPhase"; files = ( - "OBJ_104", - "OBJ_105", - "OBJ_106" + "OBJ_106", + "OBJ_107", + "OBJ_108" ); }; - "OBJ_104" = { - isa = "PBXBuildFile"; - fileRef = "OBJ_41"; - }; - "OBJ_105" = { + "OBJ_106" = { isa = "PBXBuildFile"; fileRef = "OBJ_42"; }; - "OBJ_106" = { + "OBJ_107" = { isa = "PBXBuildFile"; fileRef = "OBJ_43"; }; - "OBJ_107" = { + "OBJ_108" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_44"; + }; + "OBJ_109" = { isa = "PBXFrameworksBuildPhase"; files = ( - "OBJ_108", - "OBJ_109" + "OBJ_110", + "OBJ_111" ); }; - "OBJ_108" = { + "OBJ_11" = { + isa = "PBXGroup"; + children = ( + "OBJ_12", + "OBJ_18", + "OBJ_35" + ); + name = "Request"; + path = "Sources/Request"; + sourceTree = "SOURCE_ROOT"; + }; + "OBJ_110" = { isa = "PBXBuildFile"; fileRef = "Request::Request::Product"; }; - "OBJ_109" = { + "OBJ_111" = { isa = "PBXBuildFile"; fileRef = "Request::Json::Product"; }; - "OBJ_11" = { - isa = "PBXFileReference"; - path = "JsonProperty.swift"; - sourceTree = ""; - }; - "OBJ_110" = { + "OBJ_112" = { isa = "PBXTargetDependency"; target = "Request::Request"; }; - "OBJ_111" = { + "OBJ_113" = { isa = "PBXTargetDependency"; target = "Request::Json"; }; @@ -171,64 +181,63 @@ isa = "PBXGroup"; children = ( "OBJ_13", - "OBJ_19", - "OBJ_36" - ); - name = "Request"; - path = "Sources/Request"; - sourceTree = "SOURCE_ROOT"; - }; - "OBJ_13" = { - isa = "PBXGroup"; - children = ( "OBJ_14", "OBJ_15", "OBJ_16", - "OBJ_17", - "OBJ_18" + "OBJ_17" ); name = "Helpers"; path = "Helpers"; sourceTree = ""; }; - "OBJ_14" = { + "OBJ_13" = { isa = "PBXFileReference"; path = "Auth.swift"; sourceTree = ""; }; - "OBJ_15" = { + "OBJ_14" = { isa = "PBXFileReference"; path = "CacheType.swift"; sourceTree = ""; }; - "OBJ_16" = { + "OBJ_15" = { isa = "PBXFileReference"; path = "MediaType.swift"; sourceTree = ""; }; - "OBJ_17" = { + "OBJ_16" = { isa = "PBXFileReference"; path = "RequestError.swift"; sourceTree = ""; }; - "OBJ_18" = { + "OBJ_17" = { isa = "PBXFileReference"; path = "UserAgent.swift"; sourceTree = ""; }; - "OBJ_19" = { + "OBJ_18" = { isa = "PBXGroup"; children = ( - "OBJ_20", + "OBJ_19", + "OBJ_22", "OBJ_23", "OBJ_24", - "OBJ_25", - "OBJ_35" + "OBJ_34" ); name = "Request"; path = "Request"; sourceTree = ""; }; + "OBJ_19" = { + isa = "PBXGroup"; + children = ( + "OBJ_20", + "OBJ_21" + ); + name = "Extra"; + path = "Extra"; + sourceTree = ""; + }; "OBJ_2" = { isa = "XCConfigurationList"; buildConfigurations = ( @@ -239,70 +248,65 @@ defaultConfigurationName = "Release"; }; "OBJ_20" = { - isa = "PBXGroup"; - children = ( - "OBJ_21", - "OBJ_22" - ); - name = "Extra"; - path = "Extra"; - sourceTree = ""; - }; - "OBJ_21" = { isa = "PBXFileReference"; path = "RequestChain.swift"; sourceTree = ""; }; - "OBJ_22" = { + "OBJ_21" = { isa = "PBXFileReference"; path = "RequestGroup.swift"; sourceTree = ""; }; - "OBJ_23" = { + "OBJ_22" = { isa = "PBXFileReference"; path = "Request.swift"; sourceTree = ""; }; - "OBJ_24" = { + "OBJ_23" = { isa = "PBXFileReference"; path = "RequestBuilder.swift"; sourceTree = ""; }; - "OBJ_25" = { + "OBJ_24" = { isa = "PBXGroup"; children = ( + "OBJ_25", "OBJ_26", "OBJ_27", "OBJ_28", "OBJ_29", "OBJ_30", - "OBJ_31", - "OBJ_32" + "OBJ_31" ); name = "RequestParams"; path = "RequestParams"; sourceTree = ""; }; - "OBJ_26" = { + "OBJ_25" = { isa = "PBXFileReference"; path = "Body.swift"; sourceTree = ""; }; - "OBJ_27" = { + "OBJ_26" = { isa = "PBXFileReference"; path = "Header.swift"; sourceTree = ""; }; - "OBJ_28" = { + "OBJ_27" = { isa = "PBXFileReference"; path = "Headers.swift"; sourceTree = ""; }; - "OBJ_29" = { + "OBJ_28" = { isa = "PBXFileReference"; path = "Method.swift"; sourceTree = ""; }; + "OBJ_29" = { + isa = "PBXFileReference"; + path = "QueryParam.swift"; + sourceTree = ""; + }; "OBJ_3" = { isa = "XCBuildConfiguration"; buildSettings = { @@ -321,6 +325,7 @@ MACOSX_DEPLOYMENT_TARGET = "10.10"; ONLY_ACTIVE_ARCH = "YES"; OTHER_SWIFT_FLAGS = ( + "$(inherited)", "-DXcode" ); PRODUCT_NAME = "$(TARGET_NAME)"; @@ -345,71 +350,72 @@ name = "Debug"; }; "OBJ_30" = { - isa = "PBXFileReference"; - path = "QueryParam.swift"; - sourceTree = ""; - }; - "OBJ_31" = { isa = "PBXFileReference"; path = "RequestParam.swift"; sourceTree = ""; }; - "OBJ_32" = { + "OBJ_31" = { isa = "PBXGroup"; children = ( - "OBJ_33", - "OBJ_34" + "OBJ_32", + "OBJ_33" ); name = "Url"; path = "Url"; sourceTree = ""; }; - "OBJ_33" = { + "OBJ_32" = { isa = "PBXFileReference"; path = "ProtocolType.swift"; sourceTree = ""; }; - "OBJ_34" = { + "OBJ_33" = { isa = "PBXFileReference"; path = "Url.swift"; sourceTree = ""; }; - "OBJ_35" = { + "OBJ_34" = { isa = "PBXFileReference"; path = "Response.swift"; sourceTree = ""; }; - "OBJ_36" = { + "OBJ_35" = { isa = "PBXGroup"; children = ( - "OBJ_37" + "OBJ_36", + "OBJ_38" ); name = "SwiftUI"; path = "SwiftUI"; sourceTree = ""; }; - "OBJ_37" = { + "OBJ_36" = { isa = "PBXGroup"; children = ( - "OBJ_38" + "OBJ_37" ); - name = "RequestView"; - path = "RequestView"; + name = "RequestImage"; + path = "RequestImage"; sourceTree = ""; }; - "OBJ_38" = { + "OBJ_37" = { isa = "PBXFileReference"; - path = "RequestView.swift"; + path = "RequestImage.swift"; sourceTree = ""; }; - "OBJ_39" = { + "OBJ_38" = { isa = "PBXGroup"; children = ( - "OBJ_40" + "OBJ_39" ); - name = "Tests"; - path = ""; - sourceTree = "SOURCE_ROOT"; + name = "RequestView"; + path = "RequestView"; + sourceTree = ""; + }; + "OBJ_39" = { + isa = "PBXFileReference"; + path = "RequestView.swift"; + sourceTree = ""; }; "OBJ_4" = { isa = "XCBuildConfiguration"; @@ -426,6 +432,7 @@ ); MACOSX_DEPLOYMENT_TARGET = "10.10"; OTHER_SWIFT_FLAGS = ( + "$(inherited)", "-DXcode" ); PRODUCT_NAME = "$(TARGET_NAME)"; @@ -451,85 +458,100 @@ "OBJ_40" = { isa = "PBXGroup"; children = ( - "OBJ_41", + "OBJ_41" + ); + name = "Tests"; + path = ""; + sourceTree = "SOURCE_ROOT"; + }; + "OBJ_41" = { + isa = "PBXGroup"; + children = ( "OBJ_42", - "OBJ_43" + "OBJ_43", + "OBJ_44" ); name = "RequestTests"; path = "Tests/RequestTests"; sourceTree = "SOURCE_ROOT"; }; - "OBJ_41" = { + "OBJ_42" = { isa = "PBXFileReference"; path = "JsonTests.swift"; sourceTree = ""; }; - "OBJ_42" = { + "OBJ_43" = { isa = "PBXFileReference"; path = "RequestTests.swift"; sourceTree = ""; }; - "OBJ_43" = { + "OBJ_44" = { isa = "PBXFileReference"; path = "XCTestManifests.swift"; sourceTree = ""; }; - "OBJ_44" = { + "OBJ_45" = { isa = "PBXGroup"; children = ( - "Request::RequestTests::Product", "Request::Request::Product", - "Request::Json::Product" + "Request::Json::Product", + "Request::RequestTests::Product" ); name = "Products"; path = ""; sourceTree = "BUILT_PRODUCTS_DIR"; }; - "OBJ_48" = { + "OBJ_49" = { isa = "PBXFileReference"; path = "Resources"; sourceTree = "SOURCE_ROOT"; }; - "OBJ_49" = { - isa = "PBXFileReference"; - path = "LICENSE"; - sourceTree = ""; - }; "OBJ_5" = { isa = "PBXGroup"; children = ( "OBJ_6", "OBJ_7", - "OBJ_39", - "OBJ_44", - "OBJ_48", + "OBJ_40", + "OBJ_45", "OBJ_49", "OBJ_50", - "OBJ_51" + "OBJ_51", + "OBJ_52", + "OBJ_53" ); path = ""; sourceTree = ""; }; "OBJ_50" = { + isa = "PBXFileReference"; + path = "build"; + sourceTree = "SOURCE_ROOT"; + }; + "OBJ_51" = { + isa = "PBXFileReference"; + path = "LICENSE"; + sourceTree = ""; + }; + "OBJ_52" = { isa = "PBXFileReference"; path = "README.md"; sourceTree = ""; }; - "OBJ_51" = { + "OBJ_53" = { isa = "PBXFileReference"; path = "CONTRIBUTING.md"; sourceTree = ""; }; - "OBJ_53" = { + "OBJ_55" = { isa = "XCConfigurationList"; buildConfigurations = ( - "OBJ_54", - "OBJ_55" + "OBJ_56", + "OBJ_57" ); defaultConfigurationIsVisible = "0"; defaultConfigurationName = "Release"; }; - "OBJ_54" = { + "OBJ_56" = { isa = "XCBuildConfiguration"; buildSettings = { ENABLE_TESTABILITY = "YES"; @@ -570,7 +592,7 @@ }; name = "Debug"; }; - "OBJ_55" = { + "OBJ_57" = { isa = "XCBuildConfiguration"; buildSettings = { ENABLE_TESTABILITY = "YES"; @@ -611,25 +633,16 @@ }; name = "Release"; }; - "OBJ_56" = { + "OBJ_58" = { isa = "PBXSourcesBuildPhase"; files = ( - "OBJ_57", - "OBJ_58", - "OBJ_59" + "OBJ_59", + "OBJ_60" ); }; - "OBJ_57" = { - isa = "PBXBuildFile"; - fileRef = "OBJ_9"; - }; - "OBJ_58" = { - isa = "PBXBuildFile"; - fileRef = "OBJ_10"; - }; "OBJ_59" = { isa = "PBXBuildFile"; - fileRef = "OBJ_11"; + fileRef = "OBJ_9"; }; "OBJ_6" = { isa = "PBXFileReference"; @@ -638,20 +651,24 @@ sourceTree = ""; }; "OBJ_60" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_10"; + }; + "OBJ_61" = { isa = "PBXFrameworksBuildPhase"; files = ( ); }; - "OBJ_62" = { + "OBJ_63" = { isa = "XCConfigurationList"; buildConfigurations = ( - "OBJ_63", - "OBJ_64" + "OBJ_64", + "OBJ_65" ); defaultConfigurationIsVisible = "0"; defaultConfigurationName = "Release"; }; - "OBJ_63" = { + "OBJ_64" = { isa = "XCBuildConfiguration"; buildSettings = { ENABLE_TESTABILITY = "YES"; @@ -692,7 +709,7 @@ }; name = "Debug"; }; - "OBJ_64" = { + "OBJ_65" = { isa = "XCBuildConfiguration"; buildSettings = { ENABLE_TESTABILITY = "YES"; @@ -733,10 +750,9 @@ }; name = "Release"; }; - "OBJ_65" = { + "OBJ_66" = { isa = "PBXSourcesBuildPhase"; files = ( - "OBJ_66", "OBJ_67", "OBJ_68", "OBJ_69", @@ -754,30 +770,28 @@ "OBJ_81", "OBJ_82", "OBJ_83", - "OBJ_84" + "OBJ_84", + "OBJ_85", + "OBJ_86" ); }; - "OBJ_66" = { - isa = "PBXBuildFile"; - fileRef = "OBJ_14"; - }; "OBJ_67" = { isa = "PBXBuildFile"; - fileRef = "OBJ_15"; + fileRef = "OBJ_13"; }; "OBJ_68" = { isa = "PBXBuildFile"; - fileRef = "OBJ_16"; + fileRef = "OBJ_14"; }; "OBJ_69" = { isa = "PBXBuildFile"; - fileRef = "OBJ_17"; + fileRef = "OBJ_15"; }; "OBJ_7" = { isa = "PBXGroup"; children = ( "OBJ_8", - "OBJ_12" + "OBJ_11" ); name = "Sources"; path = ""; @@ -785,50 +799,49 @@ }; "OBJ_70" = { isa = "PBXBuildFile"; - fileRef = "OBJ_18"; + fileRef = "OBJ_16"; }; "OBJ_71" = { isa = "PBXBuildFile"; - fileRef = "OBJ_21"; + fileRef = "OBJ_17"; }; "OBJ_72" = { isa = "PBXBuildFile"; - fileRef = "OBJ_22"; + fileRef = "OBJ_20"; }; "OBJ_73" = { isa = "PBXBuildFile"; - fileRef = "OBJ_23"; + fileRef = "OBJ_21"; }; "OBJ_74" = { isa = "PBXBuildFile"; - fileRef = "OBJ_24"; + fileRef = "OBJ_22"; }; "OBJ_75" = { isa = "PBXBuildFile"; - fileRef = "OBJ_26"; + fileRef = "OBJ_23"; }; "OBJ_76" = { isa = "PBXBuildFile"; - fileRef = "OBJ_27"; + fileRef = "OBJ_25"; }; "OBJ_77" = { isa = "PBXBuildFile"; - fileRef = "OBJ_28"; + fileRef = "OBJ_26"; }; "OBJ_78" = { isa = "PBXBuildFile"; - fileRef = "OBJ_29"; + fileRef = "OBJ_27"; }; "OBJ_79" = { isa = "PBXBuildFile"; - fileRef = "OBJ_30"; + fileRef = "OBJ_28"; }; "OBJ_8" = { isa = "PBXGroup"; children = ( "OBJ_9", - "OBJ_10", - "OBJ_11" + "OBJ_10" ); name = "Json"; path = "Sources/Json"; @@ -836,53 +849,61 @@ }; "OBJ_80" = { isa = "PBXBuildFile"; - fileRef = "OBJ_31"; + fileRef = "OBJ_29"; }; "OBJ_81" = { isa = "PBXBuildFile"; - fileRef = "OBJ_33"; + fileRef = "OBJ_30"; }; "OBJ_82" = { isa = "PBXBuildFile"; - fileRef = "OBJ_34"; + fileRef = "OBJ_32"; }; "OBJ_83" = { isa = "PBXBuildFile"; - fileRef = "OBJ_35"; + fileRef = "OBJ_33"; }; "OBJ_84" = { isa = "PBXBuildFile"; - fileRef = "OBJ_38"; + fileRef = "OBJ_34"; }; "OBJ_85" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_37"; + }; + "OBJ_86" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_39"; + }; + "OBJ_87" = { isa = "PBXFrameworksBuildPhase"; files = ( - "OBJ_86" + "OBJ_88" ); }; - "OBJ_86" = { + "OBJ_88" = { isa = "PBXBuildFile"; fileRef = "Request::Json::Product"; }; - "OBJ_87" = { + "OBJ_89" = { isa = "PBXTargetDependency"; target = "Request::Json"; }; - "OBJ_89" = { + "OBJ_9" = { + isa = "PBXFileReference"; + path = "Json.swift"; + sourceTree = ""; + }; + "OBJ_91" = { isa = "XCConfigurationList"; buildConfigurations = ( - "OBJ_90", - "OBJ_91" + "OBJ_92", + "OBJ_93" ); defaultConfigurationIsVisible = "0"; defaultConfigurationName = "Release"; }; - "OBJ_9" = { - isa = "PBXFileReference"; - path = "Json.swift"; - sourceTree = ""; - }; - "OBJ_90" = { + "OBJ_92" = { isa = "XCBuildConfiguration"; buildSettings = { LD = "/usr/bin/true"; @@ -894,13 +915,15 @@ "-target", "x86_64-apple-macosx10.10", "-sdk", - "/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk" + "/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk", + "-package-description-version", + "5.1" ); SWIFT_VERSION = "5.0"; }; name = "Debug"; }; - "OBJ_91" = { + "OBJ_93" = { isa = "XCBuildConfiguration"; buildSettings = { LD = "/usr/bin/true"; @@ -912,53 +935,51 @@ "-target", "x86_64-apple-macosx10.10", "-sdk", - "/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk" + "/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk", + "-package-description-version", + "5.1" ); SWIFT_VERSION = "5.0"; }; name = "Release"; }; - "OBJ_92" = { + "OBJ_94" = { isa = "PBXSourcesBuildPhase"; files = ( - "OBJ_93" + "OBJ_95" ); }; - "OBJ_93" = { + "OBJ_95" = { isa = "PBXBuildFile"; fileRef = "OBJ_6"; }; - "OBJ_95" = { + "OBJ_97" = { isa = "XCConfigurationList"; buildConfigurations = ( - "OBJ_96", - "OBJ_97" + "OBJ_98", + "OBJ_99" ); defaultConfigurationIsVisible = "0"; defaultConfigurationName = "Release"; }; - "OBJ_96" = { + "OBJ_98" = { isa = "XCBuildConfiguration"; buildSettings = { }; name = "Debug"; }; - "OBJ_97" = { + "OBJ_99" = { isa = "XCBuildConfiguration"; buildSettings = { }; name = "Release"; }; - "OBJ_98" = { - isa = "PBXTargetDependency"; - target = "Request::RequestTests"; - }; "Request::Json" = { isa = "PBXNativeTarget"; - buildConfigurationList = "OBJ_53"; + buildConfigurationList = "OBJ_55"; buildPhases = ( - "OBJ_56", - "OBJ_60" + "OBJ_58", + "OBJ_61" ); dependencies = ( ); @@ -974,13 +995,13 @@ }; "Request::Request" = { isa = "PBXNativeTarget"; - buildConfigurationList = "OBJ_62"; + buildConfigurationList = "OBJ_63"; buildPhases = ( - "OBJ_65", - "OBJ_85" + "OBJ_66", + "OBJ_87" ); dependencies = ( - "OBJ_87" + "OBJ_89" ); name = "Request"; productName = "Request"; @@ -994,25 +1015,25 @@ }; "Request::RequestPackageTests::ProductTarget" = { isa = "PBXAggregateTarget"; - buildConfigurationList = "OBJ_95"; + buildConfigurationList = "OBJ_97"; buildPhases = ( ); dependencies = ( - "OBJ_98" + "OBJ_100" ); name = "RequestPackageTests"; productName = "RequestPackageTests"; }; "Request::RequestTests" = { isa = "PBXNativeTarget"; - buildConfigurationList = "OBJ_100"; + buildConfigurationList = "OBJ_102"; buildPhases = ( - "OBJ_103", - "OBJ_107" + "OBJ_105", + "OBJ_109" ); dependencies = ( - "OBJ_110", - "OBJ_111" + "OBJ_112", + "OBJ_113" ); name = "RequestTests"; productName = "RequestTests"; @@ -1026,9 +1047,9 @@ }; "Request::SwiftPMPackageDescription" = { isa = "PBXNativeTarget"; - buildConfigurationList = "OBJ_89"; + buildConfigurationList = "OBJ_91"; buildPhases = ( - "OBJ_92" + "OBJ_94" ); dependencies = ( ); diff --git a/Request.xcodeproj/xcshareddata/xcschemes/Request-Package.xcscheme b/Request.xcodeproj/xcshareddata/xcschemes/Request-Package.xcscheme index d347c53..797f6ac 100644 --- a/Request.xcodeproj/xcshareddata/xcschemes/Request-Package.xcscheme +++ b/Request.xcodeproj/xcshareddata/xcschemes/Request-Package.xcscheme @@ -1,82 +1,41 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + diff --git a/Resources/planned-features.md b/Resources/planned-features.md index 8e132f3..6fb014e 100644 --- a/Resources/planned-features.md +++ b/Resources/planned-features.md @@ -1,4 +1,3 @@ 1. Better `Combine` support 2. `RequestGroup` and `RequestChain` support for `RequestView` -3. `.onObject`, which parses the json body and returns a custom type (that conforms to `Codable`) 4. `Socket` and `SocketView` diff --git a/Resources/swiftui.md b/Resources/swiftui.md index 16f2978..fee96f1 100644 --- a/Resources/swiftui.md +++ b/Resources/swiftui.md @@ -47,3 +47,13 @@ struct ContentView : View { ``` #### Result: ![Result](todolist.png) + +# `RequestImage` +`RequestImage` asynchronously loads an image from the web. You can pass in a `Request` or just a `Url`: +```swift +RequestImage(Request { + Url("image.example.com/myImage.png") + Header.Authorization(.basic(username: "username", password: "password")) +}) +RequestImage(Url("image.example.com/myImage.jpg")) +``` diff --git a/Sources/Json/Json.swift b/Sources/Json/Json.swift index 8d41cbe..14a8302 100644 --- a/Sources/Json/Json.swift +++ b/Sources/Json/Json.swift @@ -13,119 +13,181 @@ import Foundation /// /// You can create `Json` by parsing a `String` or `Data`: /// -/// Json.Parse("{\"firstName\":\"Carson\"}") -/// Json.Parse("{\"firstName\":\"Carson\"}".data(using: .utf8)) -/// -/// Or you can build `Json` by hand: -/// -/// Json { -/// JsonProperty(key: "firstName", value: "Carson") -/// } +/// Json("{\"firstName\":\"Carson\"}") +/// Json("{\"firstName\":\"Carson\"}".data(using: .utf8)) /// /// You can subscript `Json` as you would expect: /// /// myJson["firstName"].string // "Carson" /// myComplexJson[0]["nestedJson"]["id"].int +/// +/// `Json` supports ` dynamicMemberLookup`, so you can subscript with much clearer syntax: +/// +/// myJson.firstName.string // "Carson" +/// myComplexJson[0].nestedJson.id.int +/// +/// You can also subscript with commas: +/// +/// myJson[0, "nestedJson", "id"].int +/// +/// This is the same as: +/// +/// myJson[0]["nestedJson"]["id"].int +@dynamicMemberLookup public struct Json { - public var properties: [JsonProperty] - /// Encodes the `Json` as `Data` - public var data: Data { - var dict: [String:Any?] = [:] - self.properties.forEach { prop in - var value = prop.value - if value is Json { - value = (prop.value as! Json).string - } else if value is JsonProperty { - value = (prop.value as! JsonProperty).string - } else if value is [JsonProperty] { - value = (prop.value as! [JsonProperty]).map({ $0.string }) - } - dict[prop.key] = value - } - return (try? JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)) ?? Data() + var jsonData: Any + + public init() { + self.jsonData = [:] } - /// Encodes the `Json` as a `String` - public var string: String { - return String(data: self.data, encoding: .utf8) ?? "" + + public init(_ rawValue: Any) { + self.jsonData = rawValue } - public init(@JsonBuilder builder: () -> JsonProperty) { - if builder().value is [JsonProperty] { - self.properties = builder().value as! [JsonProperty] - } else { - self.properties = [builder()] - } + /// Parse a JSON string using `JSONSerialization.jsonObject` to create the `Json` + public init(_ parse: String) throws { + try self.init(parse.data(using: .utf8)!) } - public init() { - self.properties = [] + /// Create `Json` from data + public init(_ data: Data) throws { + self.jsonData = try JSONSerialization.jsonObject(with: data) } - /// Parses `Json` from a `String` - /// - /// It can handle JSON objects, and arrays of JSON objects. - /// - /// Json.Parse("{\"firstName\":\"Carson\"}") - /// - /// - Parameter string: the JSON string to be parsed - public static func Parse(_ string: String) -> Json? { - var json = Json() - do { - let jsonResponse = try JSONSerialization.jsonObject(with: string.data(using: .utf8)!) - if let jsonArray = jsonResponse as? [String: Any] { - jsonArray.forEach { x in - if x.value is [String:Any] || x.value is [[String: Any]] { - let data = try! JSONSerialization.data(withJSONObject: x.value) - json.properties.append(JsonProperty(key: x.key, value: self.Parse(data)?.properties)) - } else { - json.properties.append(JsonProperty(key: x.key, value: x.value)) - } - } - } else if let jsonArray = jsonResponse as? [[String: Any]] { - jsonArray.forEach { x in - var props: [JsonProperty] = [] - x.forEach { y in - if y.value is [String:Any] || y.value is [[String: Any]] { - let data = try! JSONSerialization.data(withJSONObject: y.value) - props.append(JsonProperty(key: y.key, value: self.Parse(data)?.properties)) - } else { - props.append(JsonProperty(key: y.key, value: y.value)) - } - } - json.properties.append(JsonProperty(key: "", value: props)) - } - } else { - fatalError("Error parsing JSON; Doesn't conform to [String: Any] or [[String: Any]]") + // MARK: Subscripts + public subscript(_ sub: JsonSubscript) -> Self { + get { + var json = Self() + switch sub.jsonKey { + case .key(let s): + json.jsonData = (jsonData as! [String: Any])[s]! + case .index(let i): + json.jsonData = (jsonData as! [Any])[i] + } + return json + } + set { + switch sub.jsonKey { + case .key(let s): + var cast = jsonData as! [String: Any] + cast[s] = newValue.jsonData + jsonData = cast + case .index(let i): + var cast = jsonData as! [Any] + cast[i] = newValue.jsonData + jsonData = cast } - } catch { - print(error) - return nil } - return json + } + public subscript(_ subs: [JsonSubscript]) -> Self { + get { + subs.reduce(self) { $0[$1] } + } + set { + switch subs.count { + case 0: + return + case 1: + self[subs.first!] = newValue + default: + var newSubs = subs + newSubs.remove(at: 0) + var json = self[subs.first!] + json[newSubs] = newValue + } + } + } + public subscript(_ subs: JsonSubscript...) -> Self { + get { + self[subs] + } + set { + self[subs] = newValue + } + } + public subscript(dynamicMember member: String) -> Self { + get { + self[member] + } + set { + self[member] = newValue + } + } + + // MARK: Accessors + func accessValue(_ defaultValue: T) -> T { + accessOptional(T.self) ?? defaultValue } - /// Parses `Json` from a `Data` - /// - /// This creates the `String` for you, and is really just a convenience version of `Parse` that accepts a `String` - /// - /// Json.Parse("{\"firstName\":\"Carson\"}".data(using: .utf8)) - public static func Parse(_ data: Data) -> Json? { - guard let string = String(data: data, encoding: .utf8) else { + func accessOptional(_ type: T.Type) -> T? { + jsonData as? T + } + + /// Stringified version + public var data: Data? { + try? JSONSerialization.data(withJSONObject: jsonData) + } + + public var stringified: String? { + guard let data = data else { return nil } - return self.Parse(string) + return String(data: data, encoding: .utf8) + } + + /// The stored value of the `Json` + public var value: Any { + jsonData } - /*public static func Decode(_ type: T.Type, data: Data) -> T where T: Decodable { - return try! JSONDecoder().decode(type, from: data) - }*/ + /// The data as a non-optional `String` + public var string: String { + accessValue("") + } + /// The data as an optional `String` + public var stringOptional: String? { + accessOptional(String.self) + } + + /// The data as a non-optional `Int` + public var int: Int { + accessValue(0) + } + /// The data as an optional `Int` + public var intOptional: Int? { + accessOptional(Int.self) + } + + /// The data as a non-optional `Double` + public var double: Double { + accessValue(0.0) + } + /// The data as an optional `Double` + public var doubleOptional: Double? { + accessOptional(Double.self) + } - public subscript(index: Int) -> JsonProperty { - return properties[index] + /// The data as a non-optional `Bool` + public var bool: Bool { + accessValue(false) + } + /// The data as an optional `Bool` + public var boolOptional: Bool? { + accessOptional(Bool.self) } - public subscript(key: String) -> JsonProperty { - return properties.filter({ $0.key == key }).first! + /// The data as a non-optional `Array` + public var array: [Any] { + accessValue([]) + } + /// The data as an optional `Array` + public var arrayOptional: [Any]? { + accessOptional([Any].self) + } + /// The number of elements in the data + public var count: Int { + array.count } } diff --git a/Sources/Json/JsonBuilder.swift b/Sources/Json/JsonBuilder.swift index 75d7027..3b3a80f 100644 --- a/Sources/Json/JsonBuilder.swift +++ b/Sources/Json/JsonBuilder.swift @@ -9,11 +9,7 @@ import Foundation @_functionBuilder public struct JsonBuilder { - public static func buildBlock(_ props: JsonProperty...) -> JsonProperty { - return JsonProperty(key: "root", value: props) - } - - public static func buildBlock() -> JsonProperty { - return JsonProperty(key: "root", value: []) + public static func buildBlock(_ props: (String, Any)...) -> [(String, Any)] { + return props } } diff --git a/Sources/Json/JsonProperty.swift b/Sources/Json/JsonProperty.swift deleted file mode 100644 index 7f27818..0000000 --- a/Sources/Json/JsonProperty.swift +++ /dev/null @@ -1,61 +0,0 @@ -// -// File.swift -// -// -// Created by Carson Katri on 6/30/19. -// - -import Foundation -import SwiftUI - -/// The key-value pairs in a `Json` object -public struct JsonProperty { - public var key: String - public var value: Any? - - public init(key: String, value: Any?) { - self.key = key - self.value = value - } - - /// Retrieves the value as a non-optional `String` - public var string: String { - return value as? String ?? "" - } - - /// Retrieves the value as a non-optional `Double` - public var double: Double { - return value as? Double ?? 0.0 - } - /// Retrieves the value as a non-optional `Int` - public var int: Int { - return value as? Int ?? 0 - } - /// Retrieves the value as a non-optional `Bool` - public var bool: Bool { - return value as? Bool ?? false - } - /// Retrieves the value as a non-optional `Json` object - public var json: Json { - get { - let props = value as? [JsonProperty] ?? [JsonProperty]() - var json = Json() - json.properties = props - return json - } - } - /// Retrieves the value as a non-optional `JsonProperty` - public var property: JsonProperty { - get { - return value as? JsonProperty ?? JsonProperty(key: "", value: nil) - } - } - - public subscript(index: Int) -> JsonProperty { - return (value as! [JsonProperty])[index] - } - - public subscript(keyParam: String) -> JsonProperty { - return (value as! [JsonProperty]).filter({ $0.key == keyParam }).first! - } -} diff --git a/Sources/Json/JsonSubscript.swift b/Sources/Json/JsonSubscript.swift new file mode 100644 index 0000000..739c5e7 --- /dev/null +++ b/Sources/Json/JsonSubscript.swift @@ -0,0 +1,29 @@ +// +// Subscripts.swift +// +// +// Created by Carson Katri on 8/4/19. +// + +import Foundation + +public enum JsonSubscriptType { + case key(_ s: String) + case index(_ i: Int) +} + +public protocol JsonSubscript { + var jsonKey: JsonSubscriptType { get } +} + +extension String: JsonSubscript { + public var jsonKey: JsonSubscriptType { + .key(self) + } +} + +extension Int: JsonSubscript { + public var jsonKey: JsonSubscriptType { + .index(self) + } +} diff --git a/Sources/Json/Literals.swift b/Sources/Json/Literals.swift new file mode 100644 index 0000000..b1ddc5f --- /dev/null +++ b/Sources/Json/Literals.swift @@ -0,0 +1,50 @@ +// +// Conformance.swift +// +// +// Created by Carson Katri on 8/4/19. +// + +import Foundation + +extension Json: ExpressibleByStringLiteral { + public init(stringLiteral value: StringLiteralType) { + jsonData = value + } + public init(extendedGraphemeClusterLiteral value: StringLiteralType) { + jsonData = value + } + public init(unicodeScalarLiteral value: StringLiteralType) { + jsonData = value + } +} + +extension Json: ExpressibleByIntegerLiteral { + public init(integerLiteral value: IntegerLiteralType) { + jsonData = value + } +} + +extension Json: ExpressibleByFloatLiteral { + public init(floatLiteral value: FloatLiteralType) { + jsonData = value + } +} + +extension Json: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: BooleanLiteralType) { + jsonData = value + } +} + +extension Json: ExpressibleByArrayLiteral { + public init(arrayLiteral elements: Any...) { + jsonData = elements + } +} + +extension Json: ExpressibleByDictionaryLiteral { + public init(dictionaryLiteral elements: (String, Any)...) { + self.init { elements } + } +} diff --git a/Sources/Request/Request/Extra/RequestChain.swift b/Sources/Request/Request/Extra/RequestChain.swift index 6482941..ffe2df4 100644 --- a/Sources/Request/Request/Extra/RequestChain.swift +++ b/Sources/Request/Request/Extra/RequestChain.swift @@ -14,7 +14,7 @@ public extension Request { /// These parameters contain the results of the previously called `Request`s /// /// Request.chained { (data, err) in - /// Url("https://api.example.com/todos/\(Json.Parse(data[0]!)![0]["id"].int)") + /// Url("https://api.example.com/todos/\(Json(data[0]!)![0]["id"].int)") /// } static func chained(@RequestBuilder builder: @escaping ([Data?], [RequestError?]) -> RequestParam) -> ([Data?], [RequestError?]) -> RequestParam { return builder @@ -43,7 +43,7 @@ public struct RequestChainBuilder { /// } /// // Now we can use the data from that request to make our 2nd /// Request.chained { (data, err) in -/// Url("https://api.example.com/todos/\(Json.Parse(data[0]!)![0]["id"].int)") +/// Url("https://api.example.com/todos/\(Json(data[0]!)![0]["id"].int)") /// } /// } /// diff --git a/Sources/Request/Request/Request.swift b/Sources/Request/Request/Request.swift index 38377be..0b0b4b9 100644 --- a/Sources/Request/Request/Request.swift +++ b/Sources/Request/Request/Request.swift @@ -41,16 +41,14 @@ public typealias Request = AnyRequest /// ... /// } public class AnyRequest: ObservableObject, Identifiable where ResponseType: Decodable { - private let responseType = ResponseType.Type.self - public var willChange = PassthroughSubject() private var params: CombinedParams - private var onData: ((Data?) -> Void)? - private var onString: ((String?) -> Void)? - private var onJson: ((Json?) -> Void)? - private var onObject: ((ResponseType?) -> Void)? + private var onData: ((Data) -> Void)? + private var onString: ((String) -> Void)? + private var onJson: ((Json) -> Void)? + private var onObject: ((ResponseType) -> Void)? private var onError: ((RequestError) -> Void)? @Published public var response: Response = Response() @@ -71,25 +69,25 @@ public class AnyRequest: ObservableObject, Identifiable where Resp } /// Sets the `onData` callback to be run whenever `Data` is retrieved - public func onData(_ callback: @escaping (Data?) -> Void) -> Self { + public func onData(_ callback: @escaping (Data) -> Void) -> Self { self.onData = callback return self } /// Sets the `onString` callback to be run whenever a `String` is retrieved - public func onString(_ callback: @escaping (String?) -> Void) -> Self { + public func onString(_ callback: @escaping (String) -> Void) -> Self { self.onString = callback return self } /// Sets the `onData` callback to be run whenever `Json` is retrieved - public func onJson(_ callback: @escaping (Json?) -> Void) -> Self { + public func onJson(_ callback: @escaping (Json) -> Void) -> Self { self.onJson = callback return self } /// Sets the `onObject` callback to be run whenever `Data` is retrieved - public func onObject(_ callback: @escaping (ResponseType?) -> Void) -> Self { + public func onObject(_ callback: @escaping (ResponseType) -> Void) -> Self { self.onObject = callback return self } @@ -158,22 +156,24 @@ public class AnyRequest: ObservableObject, Identifiable where Resp } if data != nil { if self.onData != nil { - self.onData!(data) + self.onData!(data!) } if self.onString != nil { - self.onString!(String(data: data!, encoding: .utf8)) + if let string = String(data: data!, encoding: .utf8) { + self.onString!(string) + } } if self.onJson != nil { - self.onJson!(Json.Parse(String(data: data!, encoding: .utf8)!)) - /*do { - let json = try JSONSerialization.jsonObject(with: data!) - self.onJson!(json) - } catch { - fatalError(error.localizedDescription) - }*/ + if let string = String(data: data!, encoding: .utf8) { + if let json = try? Json(string) { + self.onJson!(json) + } + } } if self.onObject != nil { - self.onObject!(try? JSONDecoder().decode(ResponseType.self, from: data!)) + if let decoded = try? JSONDecoder().decode(ResponseType.self, from: data!) { + self.onObject!(decoded) + } } self.response.data = data } diff --git a/Sources/Request/SwiftUI/RequestImage/RequestImage.swift b/Sources/Request/SwiftUI/RequestImage/RequestImage.swift index 1a479b6..86f17fc 100644 --- a/Sources/Request/SwiftUI/RequestImage/RequestImage.swift +++ b/Sources/Request/SwiftUI/RequestImage/RequestImage.swift @@ -75,9 +75,9 @@ public struct RequestImage: View { } else { self.request.onData { data in #if os(OSX) - self.image = NSImage(data: data!) + self.image = NSImage(data: data) #else - self.image = UIImage(data: data!) + self.image = UIImage(data: data) #endif } .call() diff --git a/Tests/RequestTests/JsonTests.swift b/Tests/RequestTests/JsonTests.swift index cf226e9..3306aa0 100644 --- a/Tests/RequestTests/JsonTests.swift +++ b/Tests/RequestTests/JsonTests.swift @@ -8,102 +8,119 @@ import XCTest import Combine @testable import Json +@testable import Request class JsonTests: XCTestCase { - func testBuild() { - self.measure { - _ = Json { - JsonProperty(key: "firstName", value: "Carson") - } + let complexJson = """ +{ + "firstName": "Carson", + "lastName": "Katri", + "likes": [ + "programming", + "swiftui", + "webdev" + ], + "isEmployed": true, + "projects": [ + { + "name": "swift-request", + "description": "Make requests in Swift the declarative way.", + "stars": 91, + "passing": true, + "codeCov": 0.98 + }, + { + "name": "CardKit", + "description": "iOS 11 Cards in Swift", + "stars": 58, + "passing": null, + "codeCov": null + }, + ], +} +""" + func testParse() { + guard let _ = try? Json(complexJson) else { + XCTAssert(false) + return } + XCTAssert(true) } - func testBuildComplex() { - self.measure { - _ = Json { - JsonProperty(key: "firstName", value: "Carson") - JsonProperty(key: "lastName", value: "Katri") - JsonProperty(key: "likes", value: ["programming", "swiftui", "webdev"]) - JsonProperty(key: "isEmployed", value: true) - JsonProperty(key: "projects", value: [ - Json { - JsonProperty(key: "name", value: "swift-request") - JsonProperty(key: "description", value: "Make requests in Swift the declarative way.") - }, - Json { - JsonProperty(key: "name", value: "CardKit") - JsonProperty(key: "description", value: "iOS 11 Cards in Swift") - } - ]) - } + func testMeasureParse() { + measure { + let _ = try? Json(complexJson) } } - func testEncode() { - let json = Json { - JsonProperty(key: "firstName", value: "Carson") - JsonProperty(key: "lastName", value: "Katri") + func testSubscripts() { + guard let json = try? Json(complexJson) else { + XCTAssert(false) + return } - let string = json.string.replacingOccurrences(of: "\n", with: "").replacingOccurrences(of: " ", with: "") - XCTAssertTrue(string == "{\"firstName\":\"Carson\",\"lastName\":\"Katri\"}" || string == "{\"lastName\":\"Katri\",\"firstName\":\"Carson\"}") + let subscripts: [JsonSubscript] = ["projects", 0, "codeCov"] + let _: [Any] = [ + json.firstName, + json.projects[0], + json["projects", 0, "stars"], + json[subscripts] + ] } - func testEncodePerformance() { - self.measure { - _ = Json { - JsonProperty(key: "firstName", value: "Carson") - JsonProperty(key: "lastName", value: "Katri") - }.string + func testAccessors() { + guard let json = try? Json(complexJson) else { + XCTAssert(false) + return } + let _: [Any] = [ + json.firstName.string, + json.firstName.stringOptional as Any, + json.likes.array, + json.likes.arrayOptional as Any, + json.projects.count, + json.projects[0].stars.int, + json.projects[0].stars.intOptional as Any, + json.projects[0].codeCov.double, + json.projects[1].codeCov.double, + json.projects[1].codeCov.doubleOptional as Any, + json.projects[1].passing.boolOptional as Any, + json.value, + ] + XCTAssert(true) } - func testParse() { - let json = Json.Parse("{\"firstName\":\"Carson\",\"lastName\":\"Katri\"}")! - XCTAssertTrue(json["firstName"].string == "Carson" && json["lastName"].string == "Katri") + func testSet() { + guard var json = try? Json(complexJson) else { + XCTAssert(false) + return + } + json.firstName = "Cameron" + json.likes = ["Hello", "World"] + XCTAssertEqual(json["firstName"].string, "Cameron") } - func testParsePerformance() { - self.measure { - _ = Json.Parse("{\"firstName\":\"Carson\",\"lastName\":\"Katri\"}") + func testStringify() { + let _ = Json(["title": "hello", "subtitle": "world"]).data + guard let stringified = Json(["title": "hello", "subtitle": 1]).stringified else { + XCTAssert(false) + return } + XCTAssert(stringified == #"{"title":"hello","subtitle":1}"# || stringified == #"{"subtitle":1,"title":"hello"}"#) } - func testParseComplex() { + func testMeasureStringify() { self.measure { - _ = Json.Parse( -""" -{ - "firstName": "Carson", - "lastName": "Katri", - "likes": [ - "programming", - "swiftui", - "webdev" - ], - "isEmployed": true, - "projects": [ - { - "name": "swift-request", - "description": "Make requests in Swift the declarative way." - }, - { - "name": "CardKit", - "description": "iOS 11 Cards in Swift" - }, - ] -} -""") + let _ = Json(["title": "hello", "subtitle": 1]).stringified } } - static var allTests = [ - ("build", testBuild), - ("buildComplex", testBuildComplex), - ("encode", testEncode), - ("encodePerformance", testEncodePerformance), + static var allTest = [ ("parse", testParse), - ("parsePerformance", testParsePerformance), - ("parseComplex", testParseComplex), + ("measureParse", testMeasureParse), + ("subscripts", testSubscripts), + ("accessors", testAccessors), + ("stringify", testStringify), + ("measureStringify", testMeasureStringify), ] } diff --git a/Tests/RequestTests/RequestTests.swift b/Tests/RequestTests/RequestTests.swift index 4f529eb..b044b86 100644 --- a/Tests/RequestTests/RequestTests.swift +++ b/Tests/RequestTests/RequestTests.swift @@ -128,7 +128,7 @@ final class RequestTests: XCTestCase { Url("https://jsonplaceholder.typicode.com/todos") } Request.chained { (data, err) in - let json = Json.Parse(data[0]!) + let json = try? Json(data[0]!) return Url("https://jsonplaceholder.typicode.com/todos/\(json?[0]["id"].int ?? 0)") } } @@ -157,9 +157,7 @@ final class RequestTests: XCTestCase { Url("https://jsonplaceholder.typicode.com/todos") } .onObject { todos in - if todos != nil { - success = true - } + success = true expectation.fulfill() } .onError { err in From da92b388febc2048451c4149bc12149acceb1097 Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Thu, 8 Aug 2019 21:52:52 -0400 Subject: [PATCH 12/25] Fix documentation --- README.md | 4 +- .../xcschemes/Request-Package.xcscheme | 119 ++++++++++++------ 2 files changed, 82 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 768b447..bc451dd 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@ ![iOS](https://img.shields.io/badge/os-iOS-green.svg) ![macOS](https://img.shields.io/badge/os-macOS-green.svg) ![tvOS](https://img.shields.io/badge/os-tvOS-green.svg) -![build status](https://api.travis-ci.com/carson-katri/swift-request.svg) -![codecov]() +[![Build Status](https://travis-ci.com/carson-katri/swift-request.svg?branch=master)](https://travis-ci.com/carson-katri/swift-request) +[![codecov](https://codecov.io/gh/carson-katri/swift-request/branch/master/graph/badge.svg)](https://codecov.io/gh/carson-katri/swift-request) [Installation](#installation) - [Getting Started](#getting-started) - [Building a Request](#building-a-request) - [Codable](#codable) - [How it Works](#how-it-works) - [Request Groups](#request-groups) - [Request Chains](#request-chains) - [Json](#json) - [Contributing](#contributing) - [License](#license) diff --git a/Request.xcodeproj/xcshareddata/xcschemes/Request-Package.xcscheme b/Request.xcodeproj/xcshareddata/xcschemes/Request-Package.xcscheme index 797f6ac..d347c53 100644 --- a/Request.xcodeproj/xcshareddata/xcschemes/Request-Package.xcscheme +++ b/Request.xcodeproj/xcshareddata/xcschemes/Request-Package.xcscheme @@ -1,41 +1,82 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 9d56334aecbf01d1a8e21c8d9a416215901af1d1 Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Wed, 25 Sep 2019 15:37:24 -0400 Subject: [PATCH 13/25] Base64 encode Auth.basic value (#11) --- Sources/Request/Helpers/Auth.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Request/Helpers/Auth.swift b/Sources/Request/Helpers/Auth.swift index 7e942a9..dd7ae29 100644 --- a/Sources/Request/Helpers/Auth.swift +++ b/Sources/Request/Helpers/Auth.swift @@ -44,7 +44,7 @@ public struct Auth { extension Auth { /// Authenticates using `username` and `password` directly public static func basic(username: String, password: String) -> Auth { - return Auth(type: .basic, key: "\(username):\(password)") + return Auth(type: .basic, key: Data("\(username):\(password)".utf8).base64EncodedString()) } /// Authenticates using a `token` From e7a4ab09cfe55d8eca2314b968c2dc1d6b2fde7a Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Wed, 25 Sep 2019 15:44:30 -0400 Subject: [PATCH 14/25] Fix Travis build config --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c462ed9..51c1533 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,6 @@ language: - swift script: - swift package generate-xcodeproj - - xcodebuild clean test -project Request.xcodeproj -scheme "Request-Package" -destination "OS=13.0,name=iPhone XS" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO ONLY_ACTIVE_ARCH=NO -quiet -enableCodeCoverage YES -derivedDataPath .build/derivedData + - xcodebuild clean test -project Request.xcodeproj -scheme "Request-Package" -destination "OS=13.0,name=iPhone 11" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO ONLY_ACTIVE_ARCH=NO -quiet -enableCodeCoverage YES -derivedDataPath .build/derivedData after_success: - bash <(curl -s https://codecov.io/bash) -D .build/derivedData From 14128f567060b709c05aef4cd532a8270b7763b1 Mon Sep 17 00:00:00 2001 From: Egor Kolyshkin Date: Sat, 19 Oct 2019 02:42:55 +0300 Subject: [PATCH 15/25] Add buildIf realization --- Sources/Request/Request/RequestBuilder.swift | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/Sources/Request/Request/RequestBuilder.swift b/Sources/Request/Request/RequestBuilder.swift index b91d26e..e258386 100644 --- a/Sources/Request/Request/RequestBuilder.swift +++ b/Sources/Request/Request/RequestBuilder.swift @@ -10,14 +10,27 @@ import Foundation @_functionBuilder public struct RequestBuilder { public static func buildBlock(_ params: RequestParam...) -> RequestParam { + + let resultParams = params.filter { $0.children == nil } + params.compactMap { $0.children }.joined() // Multiple Urls - if params.filter({ $0.type == .url }).count > 1 { + if resultParams.filter({ $0.type == .url }).count > 1 { fatalError("You cannot specify more than 1 `Url`") } // Missing Url - if params.filter({ $0.type == .url }).count < 1 { + if resultParams.filter({ $0.type == .url }).count < 1 { fatalError("You must have a `Url`") } - return CombinedParams(children: params) + return CombinedParams(children: resultParams) + } + + public static func buildBlock(_ param: RequestParam) -> RequestParam { + return param + } + + public static func buildIf(_ param: RequestParam?) -> RequestParam { + if let param = param { + return param + } + return CombinedParams(children: []) } } From 46a7390d5aaed1323e626b91f0da9be384ca9abe Mon Sep 17 00:00:00 2001 From: Egor Kolyshkin Date: Sat, 19 Oct 2019 02:48:23 +0300 Subject: [PATCH 16/25] Add test for new case --- Tests/RequestTests/RequestTests.swift | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Tests/RequestTests/RequestTests.swift b/Tests/RequestTests/RequestTests.swift index b044b86..6c746c2 100644 --- a/Tests/RequestTests/RequestTests.swift +++ b/Tests/RequestTests/RequestTests.swift @@ -31,7 +31,16 @@ final class RequestTests: XCTestCase { Url("https://jsonplaceholder.typicode.com/todos") }) } - + + func testRequestWithCondition() { + performRequest(Request { + Url("https://jsonplaceholder.typicode.com/todos") + if true { + Method(.post) + } + }) + } + func testPost() { performRequest(Request { Url("https://jsonplaceholder.typicode.com/todos") From b0ced45d83ceb6dfb800dc5f689202d7f795e5d4 Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Mon, 21 Oct 2019 16:59:51 -0400 Subject: [PATCH 17/25] Merge travis --- .travis.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c57a51a..51c1533 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,9 @@ os: osx osx_image: xcode11 +language: + - swift script: - - xcodebuild clean test -project Request.xcodeproj -scheme "Request-Package" -destination "OS=13.0,name=iPhone XS" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO ONLY_ACTIVE_ARCH=NO -quiet + - swift package generate-xcodeproj + - xcodebuild clean test -project Request.xcodeproj -scheme "Request-Package" -destination "OS=13.0,name=iPhone 11" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO ONLY_ACTIVE_ARCH=NO -quiet -enableCodeCoverage YES -derivedDataPath .build/derivedData +after_success: + - bash <(curl -s https://codecov.io/bash) -D .build/derivedData From d57d6ea0e43cbf43de2316e519cd14c368c68ff3 Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Mon, 21 Oct 2019 17:04:47 -0400 Subject: [PATCH 18/25] Delete useless config files --- .../xcshareddata/xcschemes/Json.xcscheme | 67 ----------- .../xcschemes/Request-Package.xcscheme | 106 ------------------ .../xcshareddata/xcschemes/Request.xcscheme | 67 ----------- 3 files changed, 240 deletions(-) delete mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/Json.xcscheme delete mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/Request-Package.xcscheme delete mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/Request.xcscheme diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Json.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Json.xcscheme deleted file mode 100644 index 2765ce0..0000000 --- a/.swiftpm/xcode/xcshareddata/xcschemes/Json.xcscheme +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Request-Package.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Request-Package.xcscheme deleted file mode 100644 index 3aaeb57..0000000 --- a/.swiftpm/xcode/xcshareddata/xcschemes/Request-Package.xcscheme +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Request.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Request.xcscheme deleted file mode 100644 index f3a3fe3..0000000 --- a/.swiftpm/xcode/xcshareddata/xcschemes/Request.xcscheme +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - From 79a11514ad07004cd6359ef616b31f71c013bbc6 Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Thu, 7 Nov 2019 15:26:46 -0500 Subject: [PATCH 19/25] Hotfix EXC_BAD_ACCESS with struct workaround. --- Sources/Request/Request/Request.swift | 35 ++++++++++++------- .../SwiftUI/RequestView/RequestView.swift | 2 +- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/Sources/Request/Request/Request.swift b/Sources/Request/Request/Request.swift index eb59d9e..d009452 100644 --- a/Sources/Request/Request/Request.swift +++ b/Sources/Request/Request/Request.swift @@ -30,6 +30,7 @@ import Combine /// - Precondition: The `Request` body must contain **exactly one** `Url` public typealias Request = AnyRequest +// TODO: Fix EXC_BAD_ACCESS instead of workaround with `struct` /// Tha base class of `Request` to be used with a `Codable` `ResponseType` when using the `onObject` callback /// /// *Example*: @@ -40,8 +41,7 @@ public typealias Request = AnyRequest /// .onObject { myCodableStructs in /// ... /// } -public class AnyRequest: ObservableObject, Identifiable where ResponseType: Decodable { - public var willChange = PassthroughSubject() +public struct AnyRequest/*: ObservableObject, Identifiable*/ where ResponseType: Decodable { private var params: CombinedParams @@ -51,7 +51,7 @@ public class AnyRequest: ObservableObject, Identifiable where Resp private var onObject: ((ResponseType) -> Void)? private var onError: ((RequestError) -> Void)? - @Published public var response: Response = Response() + /*@Published*/ public var response: Response = Response() public init(@RequestBuilder builder: () -> RequestParam) { let params = builder() @@ -68,34 +68,43 @@ public class AnyRequest: ObservableObject, Identifiable where Resp self.response = Response() } + internal init(params: CombinedParams, + onData: ((Data) -> Void)?, + onString: ((String) -> Void)?, + onJson: ((Json) -> Void)?, + onObject: ((ResponseType) -> Void)?, + onError: ((RequestError) -> Void)?) { + self.params = params + self.onData = onData + self.onString = onString + self.onJson = onJson + self.onObject = onObject + self.onError = onError + } + /// Sets the `onData` callback to be run whenever `Data` is retrieved public func onData(_ callback: @escaping (Data) -> Void) -> Self { - self.onData = callback - return self + Self.init(params: params, onData: callback, onString: onString, onJson: onJson, onObject: onObject, onError: onError) } /// Sets the `onString` callback to be run whenever a `String` is retrieved public func onString(_ callback: @escaping (String) -> Void) -> Self { - self.onString = callback - return self + Self.init(params: params, onData: onData, onString: callback, onJson: onJson, onObject: onObject, onError: onError) } /// Sets the `onData` callback to be run whenever `Json` is retrieved public func onJson(_ callback: @escaping (Json) -> Void) -> Self { - self.onJson = callback - return self + Self.init(params: params, onData: onData, onString: onString, onJson: callback, onObject: onObject, onError: onError) } /// Sets the `onObject` callback to be run whenever `Data` is retrieved public func onObject(_ callback: @escaping (ResponseType) -> Void) -> Self { - self.onObject = callback - return self + Self.init(params: params, onData: onData, onString: onString, onJson: onJson, onObject: callback, onError: onError) } /// Handle any `RequestError`s thrown by the `Request` public func onError(_ callback: @escaping (RequestError) -> Void) -> Self { - self.onError = callback - return self + Self.init(params: params, onData: onData, onString: onString, onJson: onJson, onObject: onObject, onError: callback) } /// Performs the `Request`, and calls the `onData`, `onString`, `onJson`, and `onError` callbacks when appropriate. diff --git a/Sources/Request/SwiftUI/RequestView/RequestView.swift b/Sources/Request/SwiftUI/RequestView/RequestView.swift index 7729d90..bf9876f 100644 --- a/Sources/Request/SwiftUI/RequestView/RequestView.swift +++ b/Sources/Request/SwiftUI/RequestView/RequestView.swift @@ -37,7 +37,7 @@ public struct RequestView : View where Content: View, Plac } public var body: some View { - if data == nil || oldReq == nil || oldReq?.id != request.id { + if data == nil/* || oldReq == nil || oldReq?.id != request.id*/ { let req = self.request.onData { data in self.oldReq = self.request self.data = data From 8d297a4cb8913beb463843c99751fd5671b35cef Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Fri, 14 Feb 2020 13:31:02 -0500 Subject: [PATCH 20/25] Better error handling coverage --- Sources/Request/Request/Request.swift | 10 ++++++---- Tests/RequestTests/RequestTests.swift | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Sources/Request/Request/Request.swift b/Sources/Request/Request/Request.swift index d009452..046b0c5 100644 --- a/Sources/Request/Request/Request.swift +++ b/Sources/Request/Request/Request.swift @@ -154,14 +154,16 @@ public struct AnyRequest/*: ObservableObject, Identifiable*/ where // PERFORM REQUEST URLSession.shared.dataTask(with: request) { data, res, err in - if res != nil { - let statusCode = (res as! HTTPURLResponse).statusCode + if let res = res as? HTTPURLResponse { + let statusCode = res.statusCode if statusCode < 200 || statusCode >= 300 { - if self.onError != nil { - self.onError!(RequestError(statusCode: statusCode, error: data)) + if let onError = self.onError { + onError(RequestError(statusCode: statusCode, error: data)) return } } + } else if let err = err, let onError = self.onError { + onError(RequestError(statusCode: -1, error: err.localizedDescription.data(using: .utf8))) } if let data = data { if let onData = self.onData { diff --git a/Tests/RequestTests/RequestTests.swift b/Tests/RequestTests/RequestTests.swift index 8dcd4c2..3112403 100644 --- a/Tests/RequestTests/RequestTests.swift +++ b/Tests/RequestTests/RequestTests.swift @@ -176,6 +176,23 @@ final class RequestTests: XCTestCase { waitForExpectations(timeout: 10000) XCTAssert(success) } + + func testError() { + let expectation = self.expectation(description: #function) + var success = false + + Request { + Url("https://jsonplaceholder.typicode./todos") + } + .onError { err in + print(err) + success = true + expectation.fulfill() + } + .call() + waitForExpectations(timeout: 10000) + XCTAssert(success) + } static var allTests = [ ("simpleRequest", testSimpleRequest), @@ -186,5 +203,6 @@ final class RequestTests: XCTestCase { ("requestGroup", testRequestGroup), ("requestChain", testRequestChain), ("anyRequest", testAnyRequest), + ("testError", testError), ] } From f8d1dd7962fbd83f279ea972e6b4d470584d6442 Mon Sep 17 00:00:00 2001 From: Ezra Berch Date: Fri, 1 May 2020 12:45:19 -0400 Subject: [PATCH 21/25] Improve test coverage Fix Json multiple subscript setter Fix Json dictionary literal constructor --- Sources/Json/Json.swift | 1 + Sources/Json/Literals.swift | 4 +- Tests/RequestTests/JsonTests.swift | 31 ++++-- Tests/RequestTests/RequestTests.swift | 155 ++++++++++++++++++++++++-- 4 files changed, 175 insertions(+), 16 deletions(-) diff --git a/Sources/Json/Json.swift b/Sources/Json/Json.swift index 14a8302..983b2cc 100644 --- a/Sources/Json/Json.swift +++ b/Sources/Json/Json.swift @@ -96,6 +96,7 @@ public struct Json { newSubs.remove(at: 0) var json = self[subs.first!] json[newSubs] = newValue + self[subs.first!] = json } } } diff --git a/Sources/Json/Literals.swift b/Sources/Json/Literals.swift index b1ddc5f..8a2e95b 100644 --- a/Sources/Json/Literals.swift +++ b/Sources/Json/Literals.swift @@ -45,6 +45,8 @@ extension Json: ExpressibleByArrayLiteral { extension Json: ExpressibleByDictionaryLiteral { public init(dictionaryLiteral elements: (String, Any)...) { - self.init { elements } + jsonData = Dictionary(elements, uniquingKeysWith: { (value1, value2) -> Any in + return value1 + }) } } diff --git a/Tests/RequestTests/JsonTests.swift b/Tests/RequestTests/JsonTests.swift index 3306aa0..54b2131 100644 --- a/Tests/RequestTests/JsonTests.swift +++ b/Tests/RequestTests/JsonTests.swift @@ -54,17 +54,26 @@ class JsonTests: XCTestCase { } func testSubscripts() { - guard let json = try? Json(complexJson) else { + guard var json = try? Json(complexJson) else { XCTAssert(false) return } let subscripts: [JsonSubscript] = ["projects", 0, "codeCov"] - let _: [Any] = [ - json.firstName, - json.projects[0], - json["projects", 0, "stars"], - json[subscripts] - ] + + json[] = 0 + + XCTAssertEqual(json["isEmployed"].bool, true) + json["isEmployed"] = false + XCTAssertEqual(json["isEmployed"].bool, false) + + XCTAssertEqual(json["projects", 0, "stars"].int, 91) + json["projects", 0, "stars"] = 10 + XCTAssertEqual(json["projects", 0, "stars"].int, 10) + + XCTAssertEqual(json[subscripts].double, 0.98) + json[subscripts] = 0.49 + XCTAssertEqual(json[subscripts].double, 0.49) + } func testAccessors() { @@ -84,6 +93,7 @@ class JsonTests: XCTestCase { json.projects[1].codeCov.double, json.projects[1].codeCov.doubleOptional as Any, json.projects[1].passing.boolOptional as Any, + json.projects[1].passing.bool as Any, json.value, ] XCTAssert(true) @@ -95,8 +105,14 @@ class JsonTests: XCTestCase { return } json.firstName = "Cameron" + json.projects[0].stars = 100 json.likes = ["Hello", "World"] + json.projects[1] = ["name" : "hello", "description" : "world"] XCTAssertEqual(json["firstName"].string, "Cameron") + XCTAssertEqual(json["projects"][0].stars.int, 100) + XCTAssertEqual(json["likes"][0].string, "Hello") + XCTAssertEqual(json["likes"][1].string, "World") + XCTAssertEqual(json["projects"][1]["name"].string, "hello") } func testStringify() { @@ -119,6 +135,7 @@ class JsonTests: XCTestCase { ("measureParse", testMeasureParse), ("subscripts", testSubscripts), ("accessors", testAccessors), + ("set", testSet), ("stringify", testStringify), ("measureStringify", testMeasureStringify), ] diff --git a/Tests/RequestTests/RequestTests.swift b/Tests/RequestTests/RequestTests.swift index 3112403..fc0a8f8 100644 --- a/Tests/RequestTests/RequestTests.swift +++ b/Tests/RequestTests/RequestTests.swift @@ -31,10 +31,13 @@ final class RequestTests: XCTestCase { } func testRequestWithCondition() { + let condition = true performRequest(Request { - Url("https://jsonplaceholder.typicode.com/todos") - if true { - Method(.post) + if condition { + Url(protocol: .https, url: "jsonplaceholder.typicode.com/todos") + } + if !condition { + Url("invalidurl") } }) } @@ -50,6 +53,7 @@ final class RequestTests: XCTestCase { "completed": true, "userId": 3, ]) + Body("{\"userId\" : 3,\"title\" : \"My Post\",\"completed\" : true}") }) } @@ -57,10 +61,11 @@ final class RequestTests: XCTestCase { performRequest(Request { Url("https://jsonplaceholder.typicode.com/todos") Method(.get) - Query(["userId":"1"]) + Query(["userId":"1", "password": "2"]) + Query([QueryParam("key", value: "value"), QueryParam("key2", value: "value2")]) }) } - + func testComplexRequest() { performRequest(Request { Url("https://jsonplaceholder.typicode.com/todos") @@ -69,6 +74,26 @@ final class RequestTests: XCTestCase { Header.CacheControl(.noCache) }) } + + func testHeaders() { + performRequest(Request { + Url("https://jsonplaceholder.typicode.com/todos") + Header.Any(key: "Custom-Header", value: "value123") + Header.Accept(.json) + Header.Accept("text/html") + Header.Authorization(.basic(username: "carsonkatri", password: "password123")) + Header.Authorization(.bearer("authorizationToken")) + Header.CacheControl(.maxAge(1000)) + Header.CacheControl(.maxStale(1000)) + Header.CacheControl(.minFresh(1000)) + Header.ContentLength(0) + Header.ContentType(.xml) + Header.Host("jsonplaceholder.typicode.com") + Header.Origin("www.example.com") + Header.Referer("redirectfrom.example.com") + Header.UserAgent(.firefoxMac) + }) + } func testObject() { struct Todo: Decodable { @@ -101,10 +126,65 @@ final class RequestTests: XCTestCase { XCTAssert(true) } } - + + func testString() { + let expectation = self.expectation(description: #function) + var response: String? = nil + var error: Data? = nil + + _ = Request { + Url("https://jsonplaceholder.typicode.com/todos") + } + .onError { err in + error = err.error + expectation.fulfill() + } + .onString { result in + response = result + expectation.fulfill() + } + .call() + waitForExpectations(timeout: 10000) + if error != nil { + XCTAssert(false) + } else if response != nil { + XCTAssert(true) + } + } + + func testJson() { + let expectation = self.expectation(description: #function) + var response: Json? = nil + var error: Data? = nil + + _ = Request { + Url("https://jsonplaceholder.typicode.com/todos") + } + .onError { err in + error = err.error + expectation.fulfill() + } + .onJson { result in + response = result + expectation.fulfill() + } + .call() + waitForExpectations(timeout: 10000) + if error != nil { + XCTAssert(false) + } else if let response = response, response.count > 0 { + XCTAssert(true) + } + } + func testRequestGroup() { let expectation = self.expectation(description: #function) var loaded: Int = 0 + var datas: Int = 0 + var strings: Int = 0 + var jsons: Int = 0 + var errors: Int = 0 + let numberOfResponses = 10 RequestGroup { Request { Url("https://jsonplaceholder.typicode.com/todos") @@ -115,18 +195,51 @@ final class RequestTests: XCTestCase { Request { Url("https://jsonplaceholder.typicode.com/todos/1") } + Request { + Url("invalidURL") + } } .onData { (index, data) in if data != nil { loaded += 1 + datas += 1 + } + if loaded >= numberOfResponses { + expectation.fulfill() + } + } + .onString { (index, string) in + if string != nil { + loaded += 1 + strings += 1 + } + if loaded >= numberOfResponses { + expectation.fulfill() + } + } + .onJson { (index, json) in + if json != nil { + loaded += 1 + jsons += 1 } - if loaded >= 3 { + if loaded >= numberOfResponses { expectation.fulfill() } } + .onError({ (index, error) in + loaded += 1 + errors += 1 + if loaded >= numberOfResponses { + expectation.fulfill() + } + }) .call() waitForExpectations(timeout: 10000) - XCTAssertEqual(loaded, 3) + XCTAssertEqual(loaded, numberOfResponses) + XCTAssertEqual(datas, 3) + XCTAssertEqual(strings, 3) + XCTAssertEqual(jsons, 3) + XCTAssertEqual(errors, 1) } func testRequestChain() { @@ -135,6 +248,7 @@ final class RequestTests: XCTestCase { RequestChain { Request.chained { (data, err) in Url("https://jsonplaceholder.typicode.com/todos") + Method(.get) } Request.chained { (data, err) in let json = try? Json(data[0]!) @@ -150,6 +264,27 @@ final class RequestTests: XCTestCase { waitForExpectations(timeout: 10000) XCTAssert(success) } + + func testRequestChainErrors() { + let expectation = self.expectation(description: #function) + var success = false + RequestChain { + Request.chained { (data, err) in + Url("invalidurl") + } + Request.chained { (data, err) in + Url("https://jsonplaceholder.typicode.com/thispagedoesnotexist") + } + } + .call { (data, errors) in + if errors.count == 2 { + success = true + } + expectation.fulfill() + } + waitForExpectations(timeout: 10000) + XCTAssert(success) + } func testAnyRequest() { let expectation = self.expectation(description: #function) @@ -199,9 +334,13 @@ final class RequestTests: XCTestCase { ("post", testPost), ("query", testQuery), ("complexRequest", testComplexRequest), + ("headers", testHeaders), ("onObject", testObject), + ("onString", testString), + ("onJson", testJson), ("requestGroup", testRequestGroup), ("requestChain", testRequestChain), + ("requestChainErrors", testRequestChainErrors), ("anyRequest", testAnyRequest), ("testError", testError), ] From b015d25330f0b49ecdf15a86c87dc5bca09889f3 Mon Sep 17 00:00:00 2001 From: Ezra Berch Date: Fri, 1 May 2020 12:46:33 -0400 Subject: [PATCH 22/25] Remove superfluous second call of builder closure --- Sources/Request/Request/Request.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Request/Request/Request.swift b/Sources/Request/Request/Request.swift index 046b0c5..abfcb76 100644 --- a/Sources/Request/Request/Request.swift +++ b/Sources/Request/Request/Request.swift @@ -58,7 +58,7 @@ public struct AnyRequest/*: ObservableObject, Identifiable*/ where if !(params is CombinedParams) { self.params = CombinedParams(children: [params]) } else { - self.params = builder() as! CombinedParams + self.params = params as! CombinedParams } self.response = Response() } From 0db9e720a1ebe48456d89cca61523de33a4900e1 Mon Sep 17 00:00:00 2001 From: Ezra Berch Date: Mon, 25 May 2020 22:28:04 -0400 Subject: [PATCH 23/25] Add 'update' methods, which allow for repeated calls to Requests. --- README.md | 11 +++++ Sources/Request/Request/Request.swift | 60 +++++++++++++++++++++++---- Tests/RequestTests/RequestTests.swift | 19 +++++++++ 3 files changed, 83 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index bc451dd..26e8573 100644 --- a/README.md +++ b/README.md @@ -196,6 +196,17 @@ RequestChain { } ``` +## Repeated Calls +`.update` is used to run additional calls after the initial one. You can pass it either a number or a custom `Publisher`. You can also chain together multiple `.update`s. The two `.update`s in the following example are equivalent, so the end result is that the `Request` will be called once immediately and twice every 10 seconds thereafter. +```swift +Request { + Url("https://jsonplaceholder.typicode.com/todo") +} +.update(every: 10) +.update(publisher: Timer.publish(every: 10, on: .main, in: .common).autoconnect()) +.call() +``` + ## Json `swift-request` includes support for `Json`. `Json` is used as the response type in the `onJson` callback on a `Request` object. diff --git a/Sources/Request/Request/Request.swift b/Sources/Request/Request/Request.swift index abfcb76..79fc7a5 100644 --- a/Sources/Request/Request/Request.swift +++ b/Sources/Request/Request/Request.swift @@ -42,7 +42,8 @@ public typealias Request = AnyRequest /// ... /// } public struct AnyRequest/*: ObservableObject, Identifiable*/ where ResponseType: Decodable { - + public let combineIdentifier = CombineIdentifier() + private var params: CombinedParams private var onData: ((Data) -> Void)? @@ -50,6 +51,7 @@ public struct AnyRequest/*: ObservableObject, Identifiable*/ where private var onJson: ((Json) -> Void)? private var onObject: ((ResponseType) -> Void)? private var onError: ((RequestError) -> Void)? + private var updatePublisher: AnyPublisher? /*@Published*/ public var response: Response = Response() @@ -73,42 +75,51 @@ public struct AnyRequest/*: ObservableObject, Identifiable*/ where onString: ((String) -> Void)?, onJson: ((Json) -> Void)?, onObject: ((ResponseType) -> Void)?, - onError: ((RequestError) -> Void)?) { + onError: ((RequestError) -> Void)?, + updatePublisher: AnyPublisher?) { self.params = params self.onData = onData self.onString = onString self.onJson = onJson self.onObject = onObject self.onError = onError + self.updatePublisher = updatePublisher } /// Sets the `onData` callback to be run whenever `Data` is retrieved public func onData(_ callback: @escaping (Data) -> Void) -> Self { - Self.init(params: params, onData: callback, onString: onString, onJson: onJson, onObject: onObject, onError: onError) + Self.init(params: params, onData: callback, onString: onString, onJson: onJson, onObject: onObject, onError: onError, updatePublisher: updatePublisher) } /// Sets the `onString` callback to be run whenever a `String` is retrieved public func onString(_ callback: @escaping (String) -> Void) -> Self { - Self.init(params: params, onData: onData, onString: callback, onJson: onJson, onObject: onObject, onError: onError) + Self.init(params: params, onData: onData, onString: callback, onJson: onJson, onObject: onObject, onError: onError, updatePublisher: updatePublisher) } /// Sets the `onData` callback to be run whenever `Json` is retrieved public func onJson(_ callback: @escaping (Json) -> Void) -> Self { - Self.init(params: params, onData: onData, onString: onString, onJson: callback, onObject: onObject, onError: onError) + Self.init(params: params, onData: onData, onString: onString, onJson: callback, onObject: onObject, onError: onError, updatePublisher: updatePublisher) } /// Sets the `onObject` callback to be run whenever `Data` is retrieved public func onObject(_ callback: @escaping (ResponseType) -> Void) -> Self { - Self.init(params: params, onData: onData, onString: onString, onJson: onJson, onObject: callback, onError: onError) + Self.init(params: params, onData: onData, onString: onString, onJson: onJson, onObject: callback, onError: onError, updatePublisher: updatePublisher) } /// Handle any `RequestError`s thrown by the `Request` public func onError(_ callback: @escaping (RequestError) -> Void) -> Self { - Self.init(params: params, onData: onData, onString: onString, onJson: onJson, onObject: onObject, onError: callback) + Self.init(params: params, onData: onData, onString: onString, onJson: onJson, onObject: onObject, onError: callback, updatePublisher: updatePublisher) } /// Performs the `Request`, and calls the `onData`, `onString`, `onJson`, and `onError` callbacks when appropriate. public func call() { + performRequest() + if let updatePublisher = self.updatePublisher { + updatePublisher.subscribe(self) + } + } + + private func performRequest() { // Url guard var components = URLComponents(string: params.children!.filter({ $0.type == .url })[0].value as! String) else { fatalError("Missing Url in Request body") @@ -190,4 +201,39 @@ public struct AnyRequest/*: ObservableObject, Identifiable*/ where } }.resume() } + + /// Sets the `Request` to be performed additional times after the initial `call` + public func update(publisher: T) -> Self { + var newPublisher = publisher + .map {_ in Void()} + .assertNoFailure() + .eraseToAnyPublisher() + if let updatePublisher = self.updatePublisher { + newPublisher = newPublisher.merge(with: updatePublisher).eraseToAnyPublisher() + } + return Self.init(params: params, onData: onData, onString: onString, onJson: onJson, onObject: onObject, onError: onError, updatePublisher: newPublisher) + } + + /// Sets the `Request` to be repeated periodically after the initial `call` + public func update(every seconds: TimeInterval) -> Self { + self.update(publisher: Timer.publish(every: seconds, on: .main, in: .common).autoconnect()) + } +} + +extension AnyRequest : Subscriber { + public typealias Input = Void + public typealias Failure = Never + + public func receive(subscription: Subscription) { + subscription.request(.unlimited) + } + + public func receive(_ input: Void) -> Subscribers.Demand { + self.performRequest() + return .none + } + + public func receive(completion: Subscribers.Completion) { + return + } } diff --git a/Tests/RequestTests/RequestTests.swift b/Tests/RequestTests/RequestTests.swift index fc0a8f8..300585d 100644 --- a/Tests/RequestTests/RequestTests.swift +++ b/Tests/RequestTests/RequestTests.swift @@ -329,6 +329,24 @@ final class RequestTests: XCTestCase { XCTAssert(success) } + func testUpdate() { + let expectation = self.expectation(description: #function) + var numResponses = 0 + + Request { + Url("https://jsonplaceholder.typicode.com/todos") + } + .update(every: 1) + .onData { data in + numResponses += 1 + if numResponses >= 3 { + expectation.fulfill() + } + } + .call() + waitForExpectations(timeout: 10000) + } + static var allTests = [ ("simpleRequest", testSimpleRequest), ("post", testPost), @@ -343,5 +361,6 @@ final class RequestTests: XCTestCase { ("requestChainErrors", testRequestChainErrors), ("anyRequest", testAnyRequest), ("testError", testError), + ("testUpdate", testUpdate), ] } From 67407de17c23a36bfd9d8ea5bf0700ce9c506f70 Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Tue, 23 Jun 2020 10:58:57 -0400 Subject: [PATCH 24/25] Timeout support --- README.md | 8 ++++++ Sources/Request/Request/Request.swift | 20 ++++++++++++++- .../Request/Request/RequestParams/Body.swift | 2 -- .../Request/RequestParams/Header.swift | 3 +-- .../Request/RequestParams/Method.swift | 2 -- .../Request/RequestParams/QueryParam.swift | 2 -- .../Request/RequestParams/RequestParam.swift | 7 ++++++ Tests/RequestTests/RequestTests.swift | 25 ++++++++++++++++--- 8 files changed, 57 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 26e8573..103e3b9 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,14 @@ Body(["key": "value"]) Body("myBodyContent") Body(myJson) ``` +- `Timeout` + +Sets the timeout for a request or resource: +```swift +Timeout(60) +Timeout(60, for: .request) +Timeout(30, for: .resource) +``` - `RequestParam` Add a param directly diff --git a/Sources/Request/Request/Request.swift b/Sources/Request/Request/Request.swift index 79fc7a5..9d08146 100644 --- a/Sources/Request/Request/Request.swift +++ b/Sources/Request/Request/Request.swift @@ -163,8 +163,26 @@ public struct AnyRequest/*: ObservableObject, Identifiable*/ where request.httpBody = body[0].value as? Data } + // Configuration + let configuration = URLSessionConfiguration.default + let timeouts = params.children!.filter { $0.type == .timeout } + if timeouts.count > 0 { + for timeout in timeouts { + guard let (source, interval) = timeout.value as? (Timeout.Source, TimeInterval) else { + fatalError("Invalid Timeout \(timeout)") + } + if source.contains(.request) { + configuration.timeoutIntervalForRequest = interval + } + if source.contains(.resource) { + configuration.timeoutIntervalForResource = interval + } + } + } + + // PERFORM REQUEST - URLSession.shared.dataTask(with: request) { data, res, err in + URLSession(configuration: configuration).dataTask(with: request) { data, res, err in if let res = res as? HTTPURLResponse { let statusCode = res.statusCode if statusCode < 200 || statusCode >= 300 { diff --git a/Sources/Request/Request/RequestParams/Body.swift b/Sources/Request/Request/RequestParams/Body.swift index f269fe2..4b15cb2 100644 --- a/Sources/Request/Request/RequestParams/Body.swift +++ b/Sources/Request/Request/RequestParams/Body.swift @@ -26,9 +26,7 @@ import Foundation /// } public struct Body: RequestParam { public var type: RequestParamType = .body - public var key: String? public var value: Any? - public var children: [RequestParam]? /// Creates the `Body` from key-value pairs public init(_ dict: [String:Any]) { diff --git a/Sources/Request/Request/RequestParams/Header.swift b/Sources/Request/Request/RequestParams/Header.swift index 0cd7ad8..cb59051 100644 --- a/Sources/Request/Request/RequestParams/Header.swift +++ b/Sources/Request/Request/RequestParams/Header.swift @@ -11,7 +11,6 @@ public struct HeaderParam: RequestParam { public var type: RequestParamType = .header public var key: String? public var value: Any? - public var children: [RequestParam]? = nil public init(key: String, value: String) { self.key = key @@ -23,7 +22,7 @@ public struct HeaderParam: RequestParam { public struct Header { /// Sets the value for any header public static func `Any`(key: String, value: String) -> HeaderParam { - return HeaderParam(key: key, value: value) + HeaderParam(key: key, value: value) } } diff --git a/Sources/Request/Request/RequestParams/Method.swift b/Sources/Request/Request/RequestParams/Method.swift index f6bc991..97eec73 100644 --- a/Sources/Request/Request/RequestParams/Method.swift +++ b/Sources/Request/Request/RequestParams/Method.swift @@ -23,9 +23,7 @@ public enum MethodType: String { /// Sets the method of the `Request` public struct Method: RequestParam { public var type: RequestParamType = .method - public var key: String? public var value: Any? - public var children: [RequestParam]? = nil public init(_ type: MethodType) { self.value = type diff --git a/Sources/Request/Request/RequestParams/QueryParam.swift b/Sources/Request/Request/RequestParams/QueryParam.swift index d7a893e..c0b0b2f 100644 --- a/Sources/Request/Request/RequestParams/QueryParam.swift +++ b/Sources/Request/Request/RequestParams/QueryParam.swift @@ -12,7 +12,6 @@ public struct QueryParam: RequestParam { public var type: RequestParamType = .query public var key: String? public var value: Any? - public var children: [RequestParam]? public init(_ key: String, value: String) { self.key = key @@ -25,7 +24,6 @@ public struct QueryParam: RequestParam { /// `[key:value, key2:value2]` becomes `?key=value&key2=value2` public struct Query: RequestParam { public var type: RequestParamType = .query - public var key: String? public var value: Any? public var children: [RequestParam]? = [] diff --git a/Sources/Request/Request/RequestParams/RequestParam.swift b/Sources/Request/Request/RequestParams/RequestParam.swift index 1d3d3c9..9c9efb8 100644 --- a/Sources/Request/Request/RequestParams/RequestParam.swift +++ b/Sources/Request/Request/RequestParams/RequestParam.swift @@ -15,6 +15,7 @@ public enum RequestParamType { case body case header case combined + case timeout } /// A parameter used to build the `Request` @@ -25,6 +26,12 @@ public protocol RequestParam { var children: [RequestParam]? { get } } +public extension RequestParam { + var key: String? { nil } + var value: Any? { nil } + var children: [RequestParam]? { nil } +} + /// A way to create a custom `RequestParam` /// - Important: You will most likely want to use one of the builtin `RequestParam`s, such as: `Url`, `Method`, `Header`, `Query`, or `Body`. public struct AnyParam: RequestParam { diff --git a/Tests/RequestTests/RequestTests.swift b/Tests/RequestTests/RequestTests.swift index 300585d..b96738c 100644 --- a/Tests/RequestTests/RequestTests.swift +++ b/Tests/RequestTests/RequestTests.swift @@ -107,7 +107,7 @@ final class RequestTests: XCTestCase { var response: [Todo]? = nil var error: Data? = nil - _ = AnyRequest<[Todo]> { + AnyRequest<[Todo]> { Url("https://jsonplaceholder.typicode.com/todos") } .onError { err in @@ -132,7 +132,7 @@ final class RequestTests: XCTestCase { var response: String? = nil var error: Data? = nil - _ = Request { + Request { Url("https://jsonplaceholder.typicode.com/todos") } .onError { err in @@ -157,7 +157,7 @@ final class RequestTests: XCTestCase { var response: Json? = nil var error: Data? = nil - _ = Request { + Request { Url("https://jsonplaceholder.typicode.com/todos") } .onError { err in @@ -346,6 +346,25 @@ final class RequestTests: XCTestCase { .call() waitForExpectations(timeout: 10000) } + + func testTimeout() { + let expectation = self.expectation(description: #function) + + Request { + Url("http://10.255.255.1") + Timeout(1, for: .all) + } + .onError { error in + if let err = error.error, let msg = String(data: err, encoding: .utf8) { + if msg == "The request timed out." { + expectation.fulfill() + } + } + } + .call() + + waitForExpectations(timeout: 2000) + } static var allTests = [ ("simpleRequest", testSimpleRequest), From c66793474ab87e295fa49ad2f6e1e10c030a2320 Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Tue, 23 Jun 2020 13:59:04 -0400 Subject: [PATCH 25/25] Add missing file (which just happened to contain the entire new feature --- .../Request/RequestParams/Timeout.swift | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 Sources/Request/Request/RequestParams/Timeout.swift diff --git a/Sources/Request/Request/RequestParams/Timeout.swift b/Sources/Request/Request/RequestParams/Timeout.swift new file mode 100644 index 0000000..d2cc496 --- /dev/null +++ b/Sources/Request/Request/RequestParams/Timeout.swift @@ -0,0 +1,31 @@ +// +// File.swift +// +// +// Created by Carson Katri on 6/23/20. +// + +import Foundation + +/// Sets the `timeoutIntervalForRequest` and/or `timeoutIntervalForResource` of the `Request` +public struct Timeout: RequestParam { + public var type: RequestParamType = .timeout + public var value: Any? = nil + + public init(_ timeout: TimeInterval, for source: Source = .all) { + self.value = (source, timeout) + } + + public struct Source: OptionSet { + public let rawValue: Int + + public init(rawValue: Int) { + self.rawValue = rawValue + } + + public static let request = Self(rawValue: 1 << 0) + public static let resource = Self(rawValue: 1 << 1) + + public static let all: Self = [.request, .resource] + } +}