From c15809ee7b9e012a8fd36399bae6bae129fc1c3d Mon Sep 17 00:00:00 2001 From: Tomek Marciniak <16132011+mrcnk@users.noreply.github.com> Date: Fri, 29 Nov 2024 20:24:06 +0100 Subject: [PATCH] chore(worker rpc): improve error throwing (#6) --- bun.lockb | Bin 339080 -> 339816 bytes packages/utils/package.json | 1 + packages/utils/src/test/worker.ts | 10 +- packages/utils/src/worker-rpc.spec.ts | 54 +++++----- packages/utils/src/worker-rpc.ts | 140 ++++++++++++++------------ 5 files changed, 107 insertions(+), 98 deletions(-) diff --git a/bun.lockb b/bun.lockb index 7984ec7563cd9455ef308cac847faa0679dbecd2..9971bc84a92e3b175828c0b83f589c0d4406a18c 100755 GIT binary patch delta 50692 zcmeFacYIaV`t7|-He^$TP$cvwMG+)GNFb09AOfKVX?6mHCJ-Q?phAMud)UInh7@Tk zC<20o5)tW2R1_=-M`>12LBzuSj#Wb7;JLr^e(t^hyzUPpV?JX(vzIm3O4erTky59R zmYQ4d<~3jRyf3u!xgni)Ecq}pzT3VL@03_Gszv*PFJ$cAe%CkimmRJb@aS`UcF)Sb zwawOzIT&d0MN^L_=<#G#iSu}h!hoh-vbnjXZ5M_sVIPK7tFfs=hp4!ZLn#HzWFBs1 z*Lh@GYTr?)6WVw@Mer)#*4D>ht4)>Q%5ZYB&1>6vJY})(Xz%fqg3Dl6fa?)2E(%wL zPodX@cfnQQ1#l!h5ia5Jbj|8ZK#n6ic|6tNZzx#JNJduy4dF8IpXlZC**+?yf*u?+ zDoxE9o}MwPZ$^e^@%kp=J-wN4cd?^iy5Hleh1)P#t2P_tIPn^V0YlRJqz=jOcpZCEZ@bsOWWb8kqO86H zQ-?f20VAlLI;byv13WM_qi+8psRKf1y^&3RA(dv*0+>`;gEP`HG(ApY%Xt^9UZ2l2 zQR!o0HF`y8LZLF57Y5mN{eG~=b0aEgQ-`GXOFM?GT=&B&dONH(9mZcX;a!-%&l*nd zrQuohjY`=v)b8T3*h;rM$>xI0PmS66VRpK&Y%Z7e7ZIvv@^E|1J|!ZEy*Ct9xK{EO zEL9_o?4%A)9W{_n@T89()h}(>C{O=E!}`@7J=~L=VGm7$!^7(iN$;CFDh(bqbkHbI z!l=;F!XJCrg~k@CoVnmpyDfdfoY{W6-81jOnl2^A+xBbNs&jkVpq`zaY1?CARca`# zJ{di1Q2#+`{X7r$A2dXjJDFw2M^Es0DiS|xWcug<^!h4v{6l4mR?Unct@`H(Wob_R z4y*sahBZ|eIc2w=Wc%F)tDlR&)#0-f?NNLTu7cfmiruf)uW{y4$Zgoc?6E6_p|yc0C$2*!?Cau6fkx{ePK=Uu5bi=X|CO4 zM`10XJE^$*3q5Hsi60l*@uSl1&9RjeUk_IP83PABFo*^1{50R1JZo3v;fDrUoBkziRq**mw%<%x4f+~g6*~y4%f~0# zeuEd=J=}XS{a=WPtxg6nIF3&^3H$a7=u)ju7PDwC|6(403uX?yVK5f z61Yoy!y0?Cxl7z#+U`;xO1vg#|CepQKI!R0`lM#04NF%k9?u=((Wc+T|Mfd^o${?83Vhnx9wJNG4wd%RiXMD z?B!U;vBNf6ewkSpiBN&%orof^61p}0tF=8eg*Mq4TzJi{*b!_^-cPZ$3U2G`xIC$|B9Yak9_R#+E#W&itMplycb<9-s&*Zt)C`ahrPC*2&;$F((3jf zG%{mUW5>R0pQoOcFk@8esL>o3I_$H1V$iUGX(I=X%IKFi+{)+@1u27bp(7>RWS+wc zVy$qBtMcE=1 z6&<^n&3(u?BYnt&X`b32*)ygRtOAR}O31M&{h?tVPoG0}zrFLJ9Y1_f|FP)l~Dc6oa^s()KHsmc`#=AIFwshspiB9Ft9Jccw>)8D>>ZXkuH8Qovr*{wgzA2op`07b z1Y4fAb9yRt{Khhwvq_^V`#7v_a8I~nvDKcz-`HvQJ5&7)xCFX8^%r1k%?(Xs-{!_< z&3AVEkknxV28|x-8UDS!$nS==q^A8~Zx-c#wAS8TSw#q_a_w+X#?i0}ewvKb;8)Mu zlX{86Q(nKI>``Pt5W7Obg04pyoWKZksgH8bZq zg-n6f`hE@Vp6l1J?!)QnLp>i{uqWbXxQG>BcNFtt4hop~$)3~^J?n1Zo zsoQU4>HyC>SNxRDgJ0^%k*Q->{$@2Uv@$ZH!3uoTaN=~-PfNpA!=H6{9;`g4!s?h| z7ee1e)@#u4PutuGt7^jocCyZn``Ewi_-(NEwxkQ8<_?P7iWw(qCkMnq1V)#QT&11ajp=o^+f-BJ4pcM{9#Ki=^$KoIEx%*>+ zwVQc7@s@vfhZtXavrwUa@xj%IjS;<}?4~i^FGJJ%CHQV=9@^V)Yw*729uKiuflx$~ z81GY|J!zS~YVo1u{_(*9Sxj&MmYV7f zDQ*o`k37rYA-{DeR&P7cS+U_5gYz7#cl3Df%d;k6b+R3)`ukY4+9@D{2qzQbLRfwB z;?85Sk2{`CI@{H>D>e;_BGqQn9m49G=UI!^*l{$$m(eA(cSO9eXiBKi$avqNlu+`> z_~4opw-OO8W4wQc_KZyMMRg4o%7_mPB%@BDq8V|4*9dj6LcTlPP^Y}mQ+c72gpw`4 z`iyK_D>NoAv^_5r-rbGuk{4Q-7dn;~s!fmExeOwlBmOb6rsf1cve*5!6 z#e2D0x4h6oH{|_16daonh`7_^xjR&JY+PUnp*yY6&OEKkT^#%^ErZa#R_Gw1K~|{A z-5yV>6?%%09s4Vx0hV?jvn|aE?I3i&6{>cx8=64KPH{9(YtDqRYp{S&Po)TcPl%z- zVpX+@34VA#d0L~)iu1+x4(%NmAMBZGFX#f+x|ok;FZPs}81JsowDAeSFlLmdgEhZ> zUHXIyWyS}OTqV}%8=9UO@0-y#v^O(8@Ks;dQ>bWWoUeMnP;yqh@9ut~=~?lCr@2zL z4$aDp3;al^r9#0dDr6TJF)}7N2}?`KtF1412ut&q9imlCc-j6QPb`)>*UeXdUUYaM z1tC5(t7)8XPXEyK$Kr#z2-?_~)Az&#stv$WEduuuYN?QSb!gh-34zbBWv6ZpB^6=J%YxCX5AAPzL8KPoZJo%owsqJRPmjJ$a$kd7%q= zp;ixiJnb#N*@W6zp-=KcRUUG+K~|{aoMvHp((iep)?-|^S$Uz43AM4Zt2ovT^~(#r zm>2qqP?F^r^ROFwG%u8s7b@_G6YFdLNT|>g@xBRX*=-ClY)O z9}N|nAMfk`XefDpd|>ILT6YINY!*&{y`SOba_g%vhieDLjY?%L8BW4t?Cwf#@P z>VzY*~)4tx?#V#xW}=W=rdx&9m6`3 z1m3}_uX!H+3n6VE){G6c7!eGA+^!QVwR24PBUs(sXm*g``v}?|tu75znrLkS&EtZ- zCb>&ZGjbJHSG$7EVgi@2hJ_9+Y8F1(zVh0a{bN{cA=fy!(O3$=*H0n@tR{lC?V6l}sIec+dT=UuaatMa5vd&=jant$Q&k0Rm67QQmC$x77 zvuuvtb@tenm}}1vj%S@?g6*-|*y)%`^RVpADgx{NY1Llm)Tj80uYeV|st=SX>t>^{TN^0K%3n-{oN#Gcr247*Np+=gX0m{sPx z(S(v$#`{K_(Daq@-VLEWD-(j}jJpoypR~}fntdpH8mk+{SX~)j`$;ZFSoUr_FBpz} zA2y4xc}(~>SoQN_ncC%^%GVlSzo$ZbSH}m|A~p;iSREH=^RzCGgo2L~(i#X_7oHEW zx>FOz*qhWotY%oOb2_8o z61zC}!WDi8f--W2;4%btEvtpq`YTqW(1F*Qg)g;7&sw5^3|XO$P2$2oAao`D)L{5B zdm7RnrssRIw0Hw0o>#9b)QM2CLcW#Hho(1=4}6bspB2@9xw>ptbX;%}A-fhD{7YDB z5t$x}4PRlG;I}r5nOK@t^gi<_Wo4+)`grdXp?2#Nd=*!Prmv6p4Otc1i}pq+xFI1> zaJ9!X(mKJ6B{a-BXPqL{f-G23gJXiVUauQVdm2;CFn7A-IktDD*ye2b7e&PweovL=+gDLy!EjlC%s(##ER z!LpZX3f8Y!nrDGfF2})}*V-G6eSw*Q)si^+q(w~d0G9fM$-(6z{be^7nh?GkE0#Eu zyUjW^gdaz!C&4*Jgcp0o?re8Pgx`yxv9N?ti+FuSrcU@+ ztS)XcE-BtUp>}U31Pi_D@gyL7LJ>^=c34;Ty}4Mb99KrJce}A#Y61BQtq)CqD?ZS7 zz0N7K-iiyXC1jnf!cP-YTix0QJ8p10h6xya8LOR@V@h<4uk^-Hp{?=3?i)RxL{|)7 zfEAxFhrmY?tc6?RHM=Y9wbL7`bw0;ntxfqh``|Pzwb#DPoWhc`JwA0d=fAkjz|u6b zr^<1x{#I}HdEMQ&RQ2sxc?;K9?v2p&ocLgmH|+VyX?s{~7)DELJ1F#~doonYl5gdk ziovm1tthRqwO-!BQrmf2!rt{KRx_)Xqzmu89LwH?!ryhT2oW1%f}OCGCrh3c_YBs3Sb43x zgrKXbUDeLJ?4e`#>Bn6jR#)Pz85jHn%brp+!&hr}sL;Onz`eV9S`+HnDlWK?kh;ls z{=l(#io+A0ihDwZ_Q(6u_k@!7$9rE1P1~Q~3+xT;-5($9wb$M6vgw?KSn+mkI&mJr zip8>bzZ>?saoL~7hGW>gQ4UPOspiUD$EG)k4aKZu@oJ?4okjyiN8m%hm0iOXpbN%Sk0`pO!_+I^1jlnKl0x%zWEdIj`8y{9&*c&NZ_p|g!5gU1n@ zAhP#yd5QXz@waC12tu*w)=c0*NbqwW!J>6Tv-gZ2j`4}4$Sc=s}r=Q?YgzTP9 zVHoRuZeP9GA^OJz)3EH>o}CjDcn2#n)Nyj0uf!LjLPz6+?Y^+18D)}A!E!RSt~C z;rp<9U|C5+S(k$0$2^`<2=;AP|Ks^@c@ARrapGdb|HY{(&+&Pzfq7PuuRNYHdDcWM zwS(!w2D;s`!mW`j^|igZT8H-F5G-e6a96Vet1;>9v()EUPS=r3xf6D`hKI6gQwmlz zo<*&tIT@<~mX)V>b7;@k2~7CliG*PJlkPlb6Are=s)rws#+me+ux`h)&OD**alvo| z?J1nC*b-w;+0k6P2gL+tVzstL`ye4zi;FK_H=MQ)c1%kaZF?*=fHlWfJ>hg{`l;f#F_Dr7xbACILtw#^wa!L3+!L8{IlSZX7SftJ+!#vS1l9*twD z0K55bh4!3D2;Tgyy}Bs0Q;hF{Z$ru7#0OU(cEXVf%<}pLD+bFx5^Vd%gjD@Bo%QyCNpXhW~7j6pvW=1xnn{p}jxG2VX!`mFbbDF@YbjcpBa^F1*n% z&VkZ74+kGb(9qb|qCHsl^i$RU!fHgER#2?>d}#VPexY;TE;`&AuEmbUT)IET`)R1% zPYJ=Y7wp+qP?!AhFR}7>c(C-Z_5j+a&YoB*-d?raR|UfmVnZEwGz%x77TA~nk{9hw z%s!B`$5N)my%HOaq3L92xXp=j2RLvZp|$l~smX6{D$ToetXL~qF7xgcET>0l_&0fR z8t`hD@~7*CrQx@0@;sJuv7c{U#A@oq#fJax8qBHS5Ujjf24BFk2Ul??vD69lB38{m z>|UomOxV6yD!^?|@M%Y|`{i<;a|%82r`_{xmdP=`L4Rt44dftlAz0ch{4cvcjEgS3 zSgH?C_c+Nsj@1l{wNDKWVkKMkN#S60*^aVX*aOS%H5|idJC<9y@OKgNkGA)ZQ1B0y zm&a?R;3_xt zmmg};~GA%o?YW`EzgE`TwI8HT zz>*gShx=m!?_=>?V`g0NR(?6`RIhoAuYUnk$miV}IFHH=1sB|U1-;hJML#{kB^FCn zrAPSfpUO7Y9)7%MJ?o@|e$U4;iYTzjTs^};F^;zAufgQYyNzKAUt zv^&{ed|7V=!x1#MnIg?%ygN5d3wVDIR1J7M9yV#l$Kzo~wwNu}`iQ+|OJQ%BOxbLs z*5`WcBZi&P69(8=tWSO}io%e3{4o7$ef|^6g`TxOuvLD3!Hux$OBY)ou_{70SRb*1 zG~B9KQCRWC9FBnb=P98d4l7uaA4TBGZ~}avm-1EfR0KKnak#GxK4Jy?@uLL%Agqpk z#NjMh=^uwxfk_Tead?^&Khv>i!v*kr!qH78fgr+SM_2~yBUXmX9bO5CW54X!>tI#n zHCQcr8&*Yj!usUrGT5Ix`n8;St?>WY&ivb&<*$gk{s*T8|7V%;|8FwXZ2z5#s4jo- zqZnLReu$Iw;~Fkv z?k(;uV;(K;4YwL|hvRcSR^_@m@&Ad{$U7as{4D8iM;9x6@JR%?`ir_=#1)osONKmF``1 zHEb^|d!OSc#?JKYCm`)Tenh}u!b7IfM!^@p`vEo-cc0TTd ze078_%&*|60@gVR^0V|;9X&s*XEr(MHp9AbZx@@6rM+dWEorZl?0PKs4~SPiKXUxU zYR{*REmkpK!m7qGu~|d*)-pbYsip8UtdCgsWms#u2&1lnFYa(DSlN`8=&*__@7Q7m zEAvC+S<}(Q3f{sGrLPmlAEBz=brFi2v>TmkRDu)VLe6}y$4b_ccr~ky<0n=Vk{w$t zyQ9Nh99^vRU13Q*_@R2<8^*Mfkg6XJ%dxLxi`CFUuo^HJR>Bc5|2(7lp$a`L!(mlm zoTESH@Dx}sGaP%a3_f$inAQqE;Rs?~S6+lw;7hOySO@dZvymUF;3ilTVH>P@xZAN0 zI`JRCO8=q5A31yo)`UL>E8Uq)0?O!|={WqKU=?teliz=4#y`J<(%jDvWzgHnK&+Pbb!@S+p^E zXQ8WS9&_UJv-FARntz_D1XREb$1y*vA~Vs&vz&Ob?AeZ;pQX=1R{_~h{PkGnJwd#+ ztt+6<^;l6)I`Lu!7x6NqvvP&zYw5&b>%uI!K;qr^;iiu zIPqc?u+g!v$676K60eGGg|*7wg_UFWLd1`+BVO5l(!5 zR=SdoE>?M&r3fhEMn@>)*kv6q4=ck;unsj*uo5lc z+VPog;JT~?t#MQZ+Sm#HBWuXoHQ|K2z~m56*yP&vfiL zuny851r#wC_Ly;%I2K5r=g1+4pMX{VlX7!d^?KTgf5y?p%I;am7R&EB#}+Gov15xB zztqu}70|mfd)TF3u-tdW1!$!CM(m!Gw$-$GZ$?>c_F9l!jne%gnw z`t5h(;aZrspojxR$nl`#aD_L$5%BK)=jon0>7S>2ddm0D(>S3PsbSuAuCe1%j_wqmGvu@}0gU>%t_x^dh_s`S4f1d6+54H4^@Bb%H_i9@E zpC0%9$ESOnerw`=t3~GFp|Ae_{l*6)FSOY_#rw&qQZv6QUwC@|p5wp!Epupe)85nS z6z<<)X!q(*pBXl1anqjTBeos-vi97)%cIwxA68)9_pL5ahS&2~vA^IgR>Agkva`Zo*Q@#~OVUtF>G+c`(atS$R+(I)%vqm(%b?!|6IXze8d}RHa_fa@7-p+k9d2U@JGExP1+*}IcA-N&5wGE zm{N~=J9u}PMcZ{&Cqj~++jUHN=>ORX^;b&nY_ z9=9=>2!|x>GgUJYYG)x#%0xI|awQy=5S@kazL}7PFm(dL2?@C-Y63#+V+ivnAbeo#>=RJXj1Uzvdqjmz)%j2nGgeg8Z`r znI~xbs;$r-q4Ggb?{0!stZ^wM>qL-4bd%hj6nQ z@f^aK#R!Ka)G<{TBh+4kFljMDU6U)}u!QI(2)CIDOAw|mMK~cL%0w+ih+T#-e{^8RYY^@*$0eMWkhB(|yUAXQu<&Js^AdWR#FzQe_7#NXFC*M(&Pli^q5CTc zcbg@zAgo%45LkzBuSr>l(Cbx%jS}uR-d7RA*CV98ijZp7N!To*^m>H8CUrf+zzqmH zC8U{%4a}SVW{_xr$$`x7jYQYjNc12xVk7!svq$uRsrni;#EcaUHMyc;=H^XMx|tvv zZjOjXn5fOrNHa~8VUCMNnI^A8qfNHxL32j*kV$+48e^UmjWy>)51V#xLXVgwqDRed zqH!kWEoi)1Ey^_BEo$plwRHQ=RNo7yU2l8M-c5V;*;^frVk zCP%_<2{pDOOfw_4BaF#GI3!_)shWdO`)!0tIS8{%u7tx9qTfcCVI|%c4AcV|u38y6_y@N2{WWR&3a3{if3C1MuL}>di!t$L6PnvTQE=uVBF2d7h z$-4-vb|D0IAv|kRb|LiIjj&O|bH=+HA$$))+HQm;W}Sr15=!quSY}f9APn4#uv5Zv z6R{T|av#Fzy$CB!j)dJ3YV1Q;ZAR=v7_%SYkc1aa)%^&y45Z0UH5>87@g!gMi}!6!XXL!Ow~^iY9B_J z^a;WNlPlq{gy_Qv@0$sS5vCqNI3Xd|L>)nh{S;yT5rhxTaS5j-Bz=l-$Yg(tu<$d4 z^AbKWiJu{~{TyNWX9!2kISCgfbpIUTGqdD#gjHW41inD{!lZnG(Ca9|MhRaU?@@&C zFA>s?A{;mCBy5&Y`b&hbOzM{i1CJr>lyJgC97BjajxhQd!YPv@VYh@D#}Uq$5yuh6 z{0rfbgl|pNe<9TV3SrW}5WY9L5)Mm<{tDqoGvO87A-coN~fgkMeKNrbki5SE`r_|2S?a8W|{QwYDCC8rQpokj?pM)=dD zoJQz%24SOw%f@>KA^aPJv@_oJK8^^lp7HiDo28Wg1{c3c{RWqT-y-ak5HJznB1C?N zF#21Bf+k18ZV5HMLkOA?-yw|o9^sIL!lvr?2(^DenDjkDQIjj-u!QIz5Q>=zKOju~ z5#fY{2ov=qLhM6LU_&MG4*iM2Is>{zO>y7ee4KgytsYFN9u~5jILlFy71Fp7XQNN;oVbIt-z+nGl9BHGptJLW+qBAjB3xm>)p6!yK1zT0&9*gzhH0 z0K&q82HWf+NvGP3nJWU&Pli^p?f&O-DXKR!m1!bAc%0UNeLqKDul36!u`fu z2qC;MLRuk&RI^UPW(lPWBlI z5ysqra7e-frs@p{wTmH4x&dLR$(3+eLUb{NbTgqC!qnmjCnSt8QNWJe$@EP-%d!b2vp1VY=A2+K<#j5X&ZT$IqgB*G(RNlAoNr4Rz85XPC5 zQV6|DBW#qAX}qNo!f!-K(`1-n)=Ahbq4bRikDJsR5eAk)*ePL>i70~*8Hq5u48jzX zBVo6M8j%Ro%!o*YF=Y`BNtj`(mPM#t4q;MRgjpt6!eI%~Z+I28~*e#((J%l}GL_LHtw;>#ou+LPz4WV{@gh{s{ z95A^O4oirxkMO>kP#8zLMr=OkQ|(7h4DXJ$zwgjLZ9foOy;OiDCDuf_-)C46bTjS<3Q5YieW z95?GEY?e?u2H`7{8iOz}7GbA^6DA@SA+ia==vahPCP%_<2{oD^oG~MsAdG2>a7e

lRA>;IeOI-XWwIwbCTOsU}5HJy~5F%S6jBbTc(Bw$i zEulthgrFJG8evQl!XXKTP1PiX+P5Q2N#)t>L#@#!oW@lJ0;XG5uFes zJ0pzlgiy=mNZ2i*MrVYZ&4|tjW4a(5l2FG~?SfD{1z}Pbgt{hI!eI%~DG0Zj2`LCu zyCR&B5M`peBE;T-FuyB8LvvihX$eVpAViz&I}jFj^A$0_+~MosjWLPc5ZZP}_@f&_ z6TLo7e{?5F_wFQ#GfTQ7tm=Uf=z-AOr1U`O)e~W(gapGQEc&AtLRwFRM6*u9W(lQx zA+$27y?i~rt?vPZpy&YJ=uvr<$#TI+UwB|KN>Iui6z>JIWTdZT!1}+WRP@s- zI>`U1W&Mv-FPhX*zJ`U;?zjGaJnOEJn--1o{mU1)n#ULElea zzD6%^s`R+8Kp@b1m)hYJT-5!aF#7DF70RloN;Wr5_w6p~{x=l&9@HB|#3k6B)og|@ z%lqD@Ei-%xUKT*=EMHI36dl`|jQLCExFfK#`rU_I=t}=>8aCHg(^u&7_x67?Quc>U zi{|-!-oRYGjl&uYbwyDBQ9@cj{(^T?;uF5Pb<}`9>clAh2yNm=<1qb|GI2{^c#w|oj+03oYp75{kHQvqaBWqa@pZ% z?>L(NLc0>b^Uz1{e#%F`c|Ik9&u+(0$@W?bFNf@L#DWObZ87f!QT<8xO-_b-NtA!q zs}wcSRM-J0t^VZuX2(zOj>=E(U^Q^GgN~ox&uHvuxoCPh&3bhy-VqNuj(YX7g`<7! zXnNBF>vamfi>HtK_H1RsGaW6$PMhhe zf>;Sr-CF{YvOQJ7Z_0&FDcjLgjqnynEA432(aJj7jj+<*1STuMC(`k&LHJc_uc48@ zqHBT;*2@_L$|Lg6dI{hVtWPB;ac#nSzd>DI+0kw$e5cc`RUGXWH2p?ZJy+GyG;B{f zS~W+z70rG7sd}a()ZM|0oTtmSA?XjSm5 z0@p@UiyMH;%7o7?j$dX&jI)R};W~)?)0Y={esZ*W2x?I@IPWA*auV~EHTs%OtJiLK zv>5DmK%X{fDp=pK&|U(cc8(w4$)fK}vFCrXBl0CL`pR1C(;kg~`q~vw6?#T3@8tOL zojac1isaMT(fH~XPg!T&yEq!(Vq<+lhZ>oJriq>aHqj7iseZ~=>so-#jyMKK<&y}y z6Hv<^M&qBSCFly&%5ezlkXC?iiqW^sc*Z+gYr>s@8srXf65%e6mgV@}uJ#9=i8R3x z+o0(yC)A?H&{P?9v-{Nv6CFQwv%Y>r6`h2p)+GbAPTG7lHBMcx#z}k0$&aqLzRn_E zg{^fmRM+1_X)5exN9#nm8k!QguVS}tMI@ghT}`<}e@)Xm(H~oLE3McDwu2m?3x+Nb z?|_|PBY2~Lc_GnXu26YuQvp=+n)ed@)gt~RGrl~@!->GUSe!QJ6a7<~e}~Db!Fo$a zZv?#p)&ae+Rsoa+<$%6C<~~pbR0q0b)G#?M{dZK1BiIaRgHHf0Kq6=fTA8R;{yS=D zuf7`uK_Q^;y5VbrtS{B^!G3UN(~?&H1aE1*7W5u?ALt!Sy^pls{Mp)HKA@eqhN+n3 zuYTig1nUERLBsQ4Iq2gxJ(B#DGJWWNp!e#hfT>^_m=0zDy>1u+FOcR%@Df-9)`FLT zUd((BECzZByA#lC`x^TMI0;Sxy)U^5ybgE?)AJ%&qn9z)5_lQB0`&J_PXo;~tre|} z`Pd790fWH=BTanw7r{XiP%4+aALW!~N39&j&MA2x)pC(sJC z2D)nKwPRf=bY*w|3;{#IFpv(0170Kd+y}Y=y`tU{{&@1_;!MET$@ICke{0Pp1pMc)-KLkDopMb+a7oDwO6nGFk1hhwJPtYEq z^{w?h6buI=fG#p`GFn@F9`jHef6?e13>~L*R9Xxs0bQl^H9{M}P>>FWgAqVqr1Xth z*T&zztX`3O9;^T>!78vCEH)L}`ZF?z5F85h@?=}k4kQEpotIt#y^Ap|1{VimU;$N| z1N0>y>p&9mdU4R{fZ#{WUEl(1eWoeO4x*+6gVHUy18G-wR;nsEV85Ijfu z+2BLEdIr$zS?oxA`k)er3kNq-el4oE(N-hfiAeUK_d_i z>VR88T~G=X21UVc(lr9n;8t)0_yPS#a1LAm8rFNWVtrZE((BZrO{o4w{jM}LoC2HGgl-E{2auU@D+Y5I_+obTEuG`gEJvzx54Zy;T$rje!z-ni{3XXk{It;kpCW zovAJ|x@$c~+?U{Oa1<;CJDvC)@JG7+(N*aahI2c-4RFcwJOSpQJp;1@Ja2(&Bz^;a z9q1dSmV>83S@b92Ebu6J2P zur}o|-~*S?egt}%^n36zI0SOR8{l>DESL_a0)7481@inF90TfwufTC|%;A5*nG(){ zU%+YbGtepYNALsC@$)3mQB>>w8*m1k0M3(>%f|?-0Qp_3ow|;ua^!bR#(nbe-yY4)B(2uL*9B!R2$R+^*~*4tG))) z&BRTpL`qN}R#>`x)S!lNBcLfHTbaay#vmHRfF__RP+Fl0e!7>{l|vPiraO@qpsu&C zT~oD45pJ!;dcM>iB!N~yHE#`)fu2XT1-FAXK$Vf7TUckp%JW`ukBPd|U#4RfT)JW2 z0p#8l?hbkYjqPGI4T9Q!zvI&v?gRRPG|(T62jk5AJGnGHPEf8B0GpcUF<4_M?M3WK zu=cDwfjbx7X{7l&jreO9pcbFzuoj)0<``iuG@{F{CO>qAe+ejq7k~z0j*T?m9!ynpa!~nMitV=>h8$yW~=F@+w)rB80l1y8&-vMyRP)A ztP0Ztl&+p^KwK2atj~{nK=<^T!)}+m-R;`95uabnA65ljd$E&;7Nqosq|>k}9}T0X zveri|;l>(&Jy_6+D+#pU=q9u`ti4HgBDQL+8+$!GP^Ndn+MjyDoq)d1xC`hEI)G+C zcPUMQ@>ef3f#<>MjVmjh@mI~XUC2ohvelYJKw4W8HV2OrZUf&AT7yTmZ}HZt~BpG>P8Tu0SR z_X1USWDFH1ue_`6?B(o3Td^Is~|nZQXXyv-Sj=s)sx?7{a-JWZcZjz1}bMf&^^I8Sod}d;Y`Di1z-Te z6YykEgz!_~J`lp52ks}V>%&|y2h0Y~piP1&g2%yR3Yq}l4L=4etb$bFOrX4FPlKm| zDO&&23CsYqfGUv<%jptOf%AdJ|0(!s_(oW3cnQ21pT+PqKrMR?UIdafCSo4{*eBiI1e z19y+moN-s2wd^wyw8sA}!qMEr_lwx>J|W+=z|BZouFf!Sy!M6swt7!9|4l05t`ccm zv8(3rVcn_>Ou@@Ww`+@Q}2uH)pS7{G{N3q9(V-CKAomG`-JzdxME3zSv#_9k) zo!66j{cim?GN=q+gmdxv6+RDs0bhfk!4Kej@E!OTdUw)0u%|C^OZ%08qh-l(RHdOkuY`X-cPxDKoXC4A38XlmhzW4*gE89FVW_yI#er z>08{Z5Lp#e2l|an4Nwc{w=xRrZy)M|+kj3~_29Z7i#elTPKYOf285$P4A9=7jZMG6 z(B{<`ej6~v_q;wcLipVOa>f`=~jrHqxIpmaxJAZ$NdHa0c`-sQM(`QKP18IXZsOG)9>i4{(HZf6l z+WyVV@W=gG6_WW~aUs$U$f-X6!OuRbR?T}~{d$e+)#o0exhXQy-@yB^Ntoy_+xQfY z5jdt5ow8t8RIhrLV^m{2FFIMYC^g#~S$eaNnCN=->osN)$D7#`{r!Cr@#exre+QqP zWu&=hlE0C!N4%LgiO5Qc=F%j8>zh_5T7NE+Rk$T9gMv16{%ll*=(ieD=a_m?s?p6Y zO`pmBEbn3S)nxz1=mo7Xke zq>f6<;KJ~RIWWcF(7WGwr$UEK^i+S6_xPqqrus9yz9y~B*=ha;6LOroMBNe&=7qofz6zB*`3|;g4)w zK8dY}w2fBvIM{lB@4Z(%>NqiRuT84^)!E?@#5AU&bWU87xpk(Wmp+or`1kyg%&hxo zQjNPwpqVwH?M%MN>{W`%XP+-3PS)WDX#-He|_!|OR7Z%vy#_2p?kb(&M#R>a&$+Ty>x z{AkgW?d%xhxO=(X>?du7bUe!7vF_*39)J1d>0x#)ouvzHMde5^UQ3P^kMTpSyUK_N*v_=r z2`9rJzGn|j-#fXjo$Tz&l_d$4W6~;+*}e2N;bvk`ERK{7RP!x9%d_08y|^`yEJG@xBkVw zZj4jj)#+|>WB)$g9qmn*x2X1iozUqI5~hayb%Jh5|CQd;jX1Vd#@gCijYy5t1q2?*pEml^S6mxVT6Y`!Eb8(@+gLmz7?H#&i9xNSEBP_nX(ml|LtpW>rovJ-K&#+}75b*xO-$O+x9@>kKaZs5(e)y#aJuDp&`{@p?LW%At$CI5Q%OtHu-18~@Ed!7!yV2(WRA5eb#VEYu& za9-bsbDmv1&gWf^q9ek7bN6zF{Fq~Iiro46!GnK&O-9V7dQq|b(aN0V{*I+CP?F9e z=?mX4HhyXcQ{3D00dsb_zbS7AK6lVxredt;@0wG${uXop3jYL7C&yP%r%z3KE=RDh z%xx>N&YLY*zJlpy{7P2OU+MP1-1t|uq-`&MINNFwC)#LF@^E_{7J1>|!KPu)3?xRE zdnR(m%T{imQ?hzNx{)K9y76~nbk0fW zvF)L?!@F)IhBc#@h)lESWk2sz+6O$}&`dMz6(;T2OtYT@pKo%esUrJY-L)Myi(m0~ z@~$#JzT)rb`g%{A+_P*Fu50uJGwkatS(&ZtSmk!r<@47Y431+yIMHms%p7wn^Vmc) zegk{JQZwgOf7$5QCfWyt+h2Ta$dobf?xZ!&QGOdSoW!#BR{Q+IGw(c6i5RU0+IiM| zK~i6lN#+@USfuZ^Nv8LD>e70WslNes>*na*-KOd$j$419pPPYQwa5x>r`QX+ZiPwr zEu6Ex&6Sc}PnVq{xmvZ`!1{69_MTa{ffk=K6V5<(`FwTMI$u~>U#V$k?n$=ozpqa8 zG_&|M+Tpe@d77EM8N1&!Qz}fx=fD-Z1AFva5Secfy+)$6raM^Y!y1`n4>YnY-#rs%tvz zf7Vgz5w|Cf&9tQLFBMSSyE$mJfkF$A2m(I3#lb70T zXnnd?;oWj%lyI!$#C)>4@>g3Ly?DvaLXQxy+VJvDeD=myA(3R-|M!(UdsBL8vy$P_ zJpx5{$To}q{p9{X*niiU%3GKX@0ccAxMUqML$T_famr~vx%2LI3p@03%AtPOK7J_0 zk!0vLf7wF6kfb72>pahVyv5(3)W194JI@T;=8p__Jxz;k{&FS%-OtYOYPa&!L-rU} zdh+vQW8N%%#;TFEVTH`Lt^Trqn@?WFxRJYo;_a5!GtX`H2mUtE)rC8E1MUsmHJ6=u z_txavYwVTVvDo?cJSaP(^u{mL*}*|M)beFhx?m5qrB{{x?lSLdWTuSn1gRyx9JtX@Rtdz zSHG(dWKJ613+?!C9wzPMM{hhZ}ZIhn~NWxpLQ;|MvRohW`(iz?HkBPVe}; z`PdY)4lz-FG+W+bF&BE$bUMR1{Omhih5zQX^55+RUWYREbL zL=#RaJO*{j_BnMa|M#`Ma&Efsd*~o+QTwCh=(4ob$)%(hH{6x>1n8Q;{Mv?DyK{4+dZ64W-c;S_R<;8n}`E$cb3hY zN?)5PdvS6P8NCYaUWL=R)Vq=j=w;tnbSI zX{32vWS#U2y}8srHC(yw=?rUH>}P6Q&*#eesx32Hk5Yr!WoGVv8f3MvZ2sfzQRMP} ze~hzxz&CxFx%B|~IOjfYOYf&+qF-BPH@(v%Qzr+OZPPuDb8gvAjPA)Rj!vDGlm6?L zD=`br8j@D{`=nPlr~HxSc1|mAE`RU3LwD*atuv~p%x&*6I`;9H=c3k8*FMoVa0kmh z(U-sWZjWqYcs$FE+DGOx*)+bif?w28N3Q`|N$ZfRMiR9{-$m&-v}WzrFW2f1Ay} z^g`2qU(&cdZ8!Z0Ae_-w#JoC|JyC*t56aBb%BEs`XMu=A!l;QZOAFy9t3FE&<>g^; z+jPE_9X=lO`mEG{B5ke$e37$oKvPe*iqI}A{<2pYTrrhmFkd!U+o+rLd_ERQiFyqW zt%4fDvzQlQ@t*@8Hz-#1DmQ=DbZVB@6!PK*e_?h66qn$SFXE7xd)Qp#2a=M0DdKuE`HTWP{6?K;#IuAJiG zC=+!atg>oDv$qxW+Gz-7;0N68>le4yGB|JVQ%!n%pICFIy%denHqxr1nKm+cWN`kS z(c$__ZpMxWtTW)sTe4)(%Y_KV`(@DTLPUE*(SXTHa*E4|^}pw%`lQb2#SGd5gi!Z% zqY&#iCxhA-J%(l%I=BzT7d;5SRTa!B)^HO*&c*0<>V>6!1TR|(p_@I8$wL1s>{g(%!ey|z56U}( zA>4)7NE4ypG;UWo6(XA(7&nDtxM~ zP|c&Jk=`xGs<+!kN#&^KCX?5B6k)%jSI%oKQg9B%o=0DT-=EK+wYAvwsX6rT^C-b^+A$s)gtSZS5%#jc3V2(5tIEe+gFdoE(B zM(?KLi`cncSn#S@$MjT)00CE#5Q`T<% z#CMbxC^ANB=7nspX!~hIiiz(zuG90cL|;vk4Vk;N24kBmAhLO;+@#A;Qo?ytd@S?R zxqJgtzMHb4Yx4N})?H}QyOJ~!od}kB&`ahetdyFIQ$`3?0~Ad*4ZebXYL-`Nh4?1j zler4BeN=zo39lUD3MQSM254Hg(VUkwZ1M`IUWCa~;nG`zVt-OJi0Igr#u+mC5Zh*N3;S^lkWUct(NYLBHUyFjHpt``<$>k?0@Xa%|UQ;C;N5UZ$_QL6++wGFl-jA=xXr`R zR#Xf2)42weE1XYIk2@H|=L9zuOESarx(yu9s;6u@k*eu(f@a>qATv)=(jCn4Bwe@z zX-K89jhKn>nl97(_+@Up)FQk#)f+)1QrUiY zp5y-0_E{07wmxsZ1?q$st{iugBF`muksoxVYQV&J*%)Lg<6-As+qjjT+^dlJQ$76W z@TDWjJsC2qCi>m=>UA%IXOD=|d4rsSikaz)wsRI%l!_v~ z2HcTGy$*r4jbBA zIr&#eNA2allEXog^q7w7w~f<-)%>eDm)`vRndeU*S%tE)Qon~f3BeaOm-l0j%v^Uo zbC)s~oKWmzGohL`=ut_V30pSY7gq~wfZ=y!fnv!=iIN{iu@7bOjjpY>-4%^a>#dq>EU@ftUy3H$aHc}#G@{8WTO zu0aaCO49%|*xSTr$h;pq#DT#>HeblSXALu*-AD}XS7jCk8+yIueBvxgP2iCo%4 zEVof9I|I3%{Mj$@lK+xKC(YlQ7uND1I?Q*-*kiqdep1#pkg2Z4we)R!47vsgCk*QP zoZY9F!dF=ogi@VKrg97;0oVwjw5FCko#ary3kG`6Nsg07)g?J&YUArT&&R*_hFkU` zKX5^i4gZ@`NBx}Tby9d8!R&{g)5KvEA6*_&cKWut^qe{#htWDB}hZ`LO-O!#sHEPls;j*PYf+$s*aP+JXi zv$mp0{D8l`#?1=APmCUhTd=#j%VBE&wANjA)t_nLQ^R6><1Tv#Mq^MWJOQ~oIz;%# z;uvrR5KI(i_YHV+?rY&TQ9;f*3CmI^Nt$co%YLeNm;Loq8aYsq1qm7LAxB7k?^31* zmU+irzRdNGemgvZQ{j1~;f*tTj=D$pFnio=?d1vj)M+(c3_b+|U$hAGm-T$8^7&5| zrj3bW$6y)XLVTucXo45SXMzympZ^uK?e9s!hmjk^2}_1JqtPgaGy1(>P3ar+_M@$^ zL} zO#UW0%ya<{T;p zkdN$xyTm8^$iABM6vZE(vd3}S$sRRS#2@wiVenOu1Mx5(2U9Xt@{+^AfR&rh=3cUJ zLN5AeMf%FO26=@?&YdxTZghA+cx2>)$VG3x5gy4dA|^`_gmcvtIoGnNIizPm&lYcJ zf{X4c>NQQ4$;l$S%J?sUfr-a-ow7ow%D*1fcVu@#;qT?{D_&Q|juC5mGP delta 51667 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 QLDN3*V?D6?xVRes1AD(!0{{R3 diff --git a/packages/utils/package.json b/packages/utils/package.json index e328a9d..aa55899 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -18,6 +18,7 @@ }, "dependencies": { "mina-signer": "3.0.7", + "serialize-error": "^11.0.3", "superjson": "2.2.1" }, "devDependencies": { diff --git a/packages/utils/src/test/worker.ts b/packages/utils/src/test/worker.ts index 05663c6..1048622 100644 --- a/packages/utils/src/test/worker.ts +++ b/packages/utils/src/test/worker.ts @@ -1,9 +1,9 @@ import { createRpcHandler } from "../worker-rpc"; const { messageHandler } = createRpcHandler({ - methods: { - ping: async () => 'pong', - } -}) + methods: { + ping: async () => "pong", + }, +}); -self.onmessage = messageHandler +self.onmessage = messageHandler; diff --git a/packages/utils/src/worker-rpc.spec.ts b/packages/utils/src/worker-rpc.spec.ts index 19dbdf7..6aee4e8 100644 --- a/packages/utils/src/worker-rpc.spec.ts +++ b/packages/utils/src/worker-rpc.spec.ts @@ -1,32 +1,34 @@ -import { describe, it, expect, mock, beforeAll } from 'bun:test' -import { createRpc, createRpcHandler } from './worker-rpc' +import { beforeAll, describe, expect, it, mock } from "bun:test"; +import { createRpc, createRpcHandler } from "./worker-rpc"; describe("Worker RPC", () => { - let worker: Worker + let worker: Worker; - beforeAll(() => { - worker = new Worker(new URL('./test/worker.ts', import.meta.url)) - }) + beforeAll(() => { + worker = new Worker(new URL("./test/worker.ts", import.meta.url)); + }); - it("creates RPC handler", async () => { - const mockedHandler = mock(async () => "pong") - const { messageHandler } = createRpcHandler({ - methods: { - ping: mockedHandler, - } - }) - await messageHandler(new MessageEvent('message', { data: { method: 'ping', params: [] } })) - expect(mockedHandler).toHaveBeenCalled() - }) + it("creates RPC handler", async () => { + const mockedHandler = mock(async () => "pong"); + const { messageHandler } = createRpcHandler({ + methods: { + ping: mockedHandler, + }, + }); + await messageHandler( + new MessageEvent("message", { data: { method: "ping", params: [] } }), + ); + expect(mockedHandler).toHaveBeenCalled(); + }); - it("exchanges messages with Web Worker", async () => { - const rpc = createRpc({ worker }) - const response = await rpc.request({ method: 'ping', params: [] }) - expect(response.result).toBe('pong') - }) + it("exchanges messages with Web Worker", async () => { + const rpc = createRpc({ worker }); + const response = await rpc.request({ method: "ping", params: [] }); + expect(response.result).toBe("pong"); + }); - it("calls non-existing method", async () => { - const rpc = createRpc({ worker }) - expect(rpc.request({ method: 'pang', params: [] })).rejects.toThrow() - }) -}) + it("calls non-existing method", async () => { + const rpc = createRpc({ worker }); + expect(rpc.request({ method: "pang", params: [] })).rejects.toThrow(); + }); +}); diff --git a/packages/utils/src/worker-rpc.ts b/packages/utils/src/worker-rpc.ts index 1da9e2b..7bdeaa7 100644 --- a/packages/utils/src/worker-rpc.ts +++ b/packages/utils/src/worker-rpc.ts @@ -1,93 +1,99 @@ -import { z } from "zod"; +import { deserializeError, serializeError } from "serialize-error"; import superjson from "superjson"; +import { z } from "zod"; const DEFAULT_TIMEOUT = 60000; export const RequestSchema = z.object({ - method: z.string(), - params: z.array(z.string()).optional(), + method: z.string(), + params: z.array(z.string()).optional(), }); type RequestParams = z.infer; export const ResponseSchema = z - .object({ - id: z.string(), - result: z.any().optional(), - error: z.string().optional(), - }) - .strict(); + .object({ + id: z.string(), + result: z.any().optional(), + error: z.string().optional(), + }) + .strict(); type Response = z.infer; export type RequestFn = (params: RequestParams) => Promise; export const createRpc = ({ - worker, - timeout, + worker, + timeout, }: { - worker: Worker; - timeout?: number; + worker: Worker; + timeout?: number; }) => { - const request: RequestFn = async ({ method, params }) => { - let resolved = false; - return new Promise((resolve, reject) => { - console.log('>>>M', method, params) - setTimeout(() => { - if (resolved) return; - return reject(new Error("[WorkerRPC] Timeout reached.")); - }, timeout ?? DEFAULT_TIMEOUT); - const responseListener = (event: MessageEvent) => { - resolved = true; - worker.removeEventListener("message", responseListener); - const data = superjson.parse(event.data); - const response = ResponseSchema.parse(data); - if (response.error) - return reject(new Error(`[WorkerRPC] ${response.error}`)); - return resolve(response); - }; - worker.addEventListener("message", responseListener); - worker.postMessage({ method, params }); - }); - }; - return { - request, - }; + const request: RequestFn = async ({ method, params }) => { + let resolved = false; + return new Promise((resolve, reject) => { + setTimeout(() => { + if (resolved) return; + return reject(new Error("[WorkerRPC] Timeout reached.")); + }, timeout ?? DEFAULT_TIMEOUT); + const responseListener = (event: MessageEvent) => { + resolved = true; + worker.removeEventListener("message", responseListener); + const data = superjson.parse(event.data); + const response = ResponseSchema.parse(data); + if (response.error) { + const errorObject = superjson.parse(response.error); + const deserializedError = deserializeError(errorObject); + return reject(deserializedError); + } + return resolve(response); + }; + worker.addEventListener("message", responseListener); + worker.postMessage({ method, params }); + }); + }; + return { + request, + }; }; type Method = (params: string[]) => Promise; type MethodsMap = Record; -const respond = (data: unknown) => postMessage(superjson.stringify(data)) +const respond = (data: unknown) => postMessage(superjson.stringify(data)); export const createRpcHandler = ({ methods }: { methods: MethodsMap }) => { - const methodKeys = Object.keys(methods); - if (methodKeys.length === 0) throw new Error("No methods provided."); - const MethodEnum = z.enum(['error', ...methodKeys]); - const ExtendedRequestSchema = RequestSchema.extend({ - method: MethodEnum, - }).strict(); - const ExtendedResponseSchema = ResponseSchema.extend({ - id: MethodEnum, - }).strict(); - const messageHandler = async (event: MessageEvent) => { - try { - const action = ExtendedRequestSchema.parse(event.data) - const callable = methods[action.method] - if (!callable) throw new Error(`Method "${action.method}" not found.`); - const result = await callable(action.params ?? []); - const parsedResult = ExtendedResponseSchema.parse({ - id: action.method, - result, - }); - return respond(parsedResult); - // biome-ignore lint/suspicious/noExplicitAny: Error handling - } catch (error: any) { - return respond(ExtendedResponseSchema.parse({ - id: 'error', - error: `[WorkerRPC] ${error.message}`, - })); - } - }; - return { messageHandler }; + const methodKeys = Object.keys(methods); + if (methodKeys.length === 0) throw new Error("No methods provided."); + const MethodEnum = z.enum(["error", ...methodKeys]); + const ExtendedRequestSchema = RequestSchema.extend({ + method: MethodEnum, + }).strict(); + const ExtendedResponseSchema = ResponseSchema.extend({ + id: MethodEnum, + }).strict(); + const messageHandler = async (event: MessageEvent) => { + try { + const action = ExtendedRequestSchema.parse(event.data); + const callable = methods[action.method]; + if (!callable) throw new Error(`Method "${action.method}" not found.`); + const result = await callable(action.params ?? []); + const parsedResult = ExtendedResponseSchema.parse({ + id: action.method, + result, + }); + return respond(parsedResult); + // biome-ignore lint/suspicious/noExplicitAny: Error handling + } catch (error: any) { + const serializedError = superjson.stringify(serializeError(error)); + return respond( + ExtendedResponseSchema.parse({ + id: "error", + error: serializedError, + }), + ); + } + }; + return { messageHandler }; };