From 65092c27cb9c563ae5cb30193d00f9c794510055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Tue, 6 Feb 2024 03:15:39 +0100 Subject: [PATCH] 0.1.0 (#1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Julien Valverdé Reviewed-on: https://git.jvalver.de/Thilawyn/traitify-ts/pulls/1 --- bun.lockb | Bin 155330 -> 155678 bytes package.json | 13 ++- rollup.config.ts | 54 ++++++----- src/Trait.ts | 153 +++++++++++++++++++++++++++++++ src/TraitExpression.ts | 117 ++++++++++++++++++++++++ src/TraitExpressionBuilder.ts | 131 +++++++++++++++++++++++++++ src/abstract.ts | 10 +++ src/expresses.ts | 84 ----------------- src/index.ts | 6 +- src/lib.ts | 6 ++ src/tests.ts | 164 ++++++++++++---------------------- src/trait.ts | 117 ------------------------ src/util/class.ts | 66 -------------- src/util/extend.ts | 25 ++++++ src/util/index.ts | 4 +- src/util/inheritance.ts | 8 +- src/util/lib.ts | 6 ++ src/util/misc.ts | 25 ++++++ src/util/trait.ts | 16 ---- 19 files changed, 582 insertions(+), 423 deletions(-) create mode 100644 src/Trait.ts create mode 100644 src/TraitExpression.ts create mode 100644 src/TraitExpressionBuilder.ts create mode 100644 src/abstract.ts delete mode 100644 src/expresses.ts create mode 100644 src/lib.ts delete mode 100644 src/trait.ts delete mode 100644 src/util/class.ts create mode 100644 src/util/extend.ts create mode 100644 src/util/lib.ts create mode 100644 src/util/misc.ts delete mode 100644 src/util/trait.ts diff --git a/bun.lockb b/bun.lockb index 1263665f93f6bc4a12cda1f583a67208e60cbb22..1aa0c800bb2453190ab6462bf94fee3e72b2f76d 100755 GIT binary patch delta 27128 zcmeIb33OG(*6+J(lR!2Q`YwbnG(vy`LYIUmpl|NIgk0+IxyZ`!DUN<5l6<@7_I3>JMoI?J4zGfg z41$qTfNK=6BJvbcZtx*e;@@%jVm($>&M95W^PBgbctP9H)Yt}Ws5V46GEmN~f#C@bOIH@Qf? zwxO(&;3c>Z`4wE^pW-4ii;K9?fQ#5?56gIX*f@`8JzVT3r;Z+-o;}`E9WM6i*+VkN zbK|m(eHuzh*Qbi)ljF(VNkCe7SoYA=(Wz;}y1=D`Es;`h-&2WFpI;$Ge;6tCz6ps* z?tNq^c5RVjx0upPK{QhApK@ep3PFnnjwCTTVvoTp2QQ4W}#>YzaVK<)a0AuAOV&n8Fz zEqcnBdvAT)kvAMUZm3v!Jne{=n#xEYlaro7W2KKtw<2mZurt&o5QFqcJEL<*sgWiP z?HW1&m#W+emjbMVOH+)nTH52O-`KVfMM^=!9qvI&liVF;$Hzxe|2`ByH?lK6j}%W2 zBc%X~qU{WJI{Ne`b_T9~)Ue49OUWBIwF~kf@zNJsBc&6sA)QPTi;z;_6)`q{#?hb3 zajGgkJBr%&cs_!QVY%k^jf){mz}*_cZfH6;9GV`LK4y5PXAAZcKQc8tYI5qhF>4%t zqlN9r#Fln}1|h}s(MYlH?Z~i87)r#+R<>a-nM;lA)Oo@6b2i7>tQFZx*X$H;%h%AC zgcrgkyM0Kh=s(a4f7_96ZZA6dJnzVvNXgI5=U?*=ZDUP-wQt?v0SX|+a=T7LxD?>J zPAytFr+uQ`F)R3OXR=bqkBp*is$eBU?ML)-y9-DuUP&kQxb%#1slz><5u-C@Zt@In zZ^zRy)3Z{uv)wsmPhI=&Bk#8FvlS`sw#A-O-Jjd1gWaxOkW!m&y}9+VtD~*2(8(@H z6bYqYxXp2s8^{p9j1>JC-KAKQh;uM0ZXKo$DgLO@!zM7(d9uc3juTj zJj=<=ipogMqF4t}NJNv~c16`iitATNAQ`RdV)OHGDSiPrkOFLa(AE!vhr-8C7#{Ty zerNWvc>%H_`gr22AbUCKB9Uce_OIC0UQT-Swb#2Cq^y5I=*5$aWIO&mQr5GKes+dm zBBfwQky7wfWJ%<4?4)1}$jpgjJf4IBc0p!2Elk@DjT)Uf;yezOqY$|p2}lNSr`QFM z-2@Y2_Ji;W=vNH1tM({%QlPj&cAwr2mm7Wxmzr9nRq^_fPcRWnu`q-5+4VAsuV=%upU?lNSQT_8na%cH+OSPGKh$(_-~ZqA`7B*S6w+Q>kL zopC?7++cKOT59%4k7spV+k*vqNr}p8mfl#Re$Kc|TlYwoU0XxOr4AiNAN;4oTaUGG z{tVJbUYY16Pv&x~+#SZ*=?0-MgMN5w_IOM^O_eDx~*gw&Bh*^~T>Ca1+i)lk2t4UNdq?mj%$u7!vq%_2|N9;1Mcl1kj zL}=xZHIcb@rydN?S{oPoMaj@vWS4+#5VE+Ah;F3IR1FFKK(zXFWP-PZ(*3F?st0sl zRljeJ@_6Df_UhECv1*qN3-|jfdOaSd%3P(-){9jmbzZnX_#txZr1QfQf>#r|*9!ei zsEZZy2fMLP60&s%2-$WOin_7MgzVT?2z9s8UcIG@E9UX^v~)8F*|A3n*|~&=xM|Y} z*=1RFOZNjIJB6R7vr{}pC}8Dxh>(5Xs?@4&H-eC@dz+AzpZZDXMfig!(pW8Ye$|BF z#*DsxR_G~0eXY>vw{&szp8Iw6dToLT47MV_B{V>vuH7bx9++mSmJ=Fig+gdSLUq~% z5g1^p-m_KQs#ZDo29pT&ky!PyPOj%y9$m<_k9FOm!|w8{-*ht9B%ODc-?yB}t+myF z(pXn@Sbe{@K}FrKexe$#^B^rM=@XF0byx$xZ+j)%x~Md*?*^c%$HR8Q?iJoLVY*+#MAcd6HT0|5x{&K>9oES2tyfj| zYm}%4>%2yO^@c8N%7K(ueX{$(Ku0c)L~J6 zm7|lnUe)_ELO+8!yrO^Bvx(Lh0Xll5_NUe=83*hjBRn2`feQSD|MI0!xqbS-Pg@w zR_*(qhBYOwh(6mPF66&N6{+v>bR?>n)o2gE+QC9}YQtFHI}R(Vmqf>^A9Qj{zb~?Z z$I}A~ua0ON7X*pZDJ>J!Y8}=}S}D1e-xnTfn*>X_)I?o~?h3m0BvX1x-#FD!_lr&R zO=#%xbhC6~w_g{=`h6uDQH8c${a9ZLtO=~7J{uJq+`KV`)2Hht1ZNZKXoU(~o$nVy zcVo+B6BX<05oJ4~EcOqW^y6U5t=%wbYTTL-r=oSg)``9z(RP{bzPlVIl~Tm&MptxL zg5UQr1(Ezi^pb>xV2QQs_ILDBw?R6hL98#9ptJ%hqhoy&VE0*ZQk}bCNp`wsvA$|C z_C#n`d>Tx;F&&q5o1HkX#fmh$Rr*%3-nPy3iMENpX((Hez$&m>r;`)?-dfG|!o);h zTJt;0@Cpofs23TPpTJ0Im(S~Mp%?lSeQ{(Yg|-|Dei#-fmFrvO=&gGM7jMZg8#+HR zL55^IzwabmD#V(}z13Uke(e)|{TcF-l}D$xj`ilX(kJRA`mUn1t3it3=c}qT22GO~ zt0wEbyZycm=wzj^dYbPVOnkG7?5!K8`*le4^&wtLUd(F44`7lBtwBHW#oH}f%wjzq zW_R1!I=I85S-T7Bg;hXq-k{+urC zg2@oG(`l-KdijY9kaPP#};D-n{v-FE3gx+r9k74(?%p2jC7Vr-BTQlm5I=QPq z_@eEpPzIevEMU{cs1o!TMRcNj)KI4xP$=ww&ARrKI~u+BQAVS?`!LUtOuN$?l2 zd#q{WE=q$%{e<9YgnC%jSV+jJ#(QFYVT?w5`I3}9VT_4xZFE>Kzi%Uq*+%Z&F*f)- zEYZp}s2$PD!p2|1^2mZCJB#zBTg)Ls&*^ zY^-ck$hpNkdDS}=TVdfR^6agV_y9V;gF zwFPFk{*vKwK@VCDm6+hWn~*e=z2ZEqlT-Y@T@s7VUc-v?u`7<|N{sa;^wCuZCi)&l zDTB`LA^Ty{hSrSitDIy{BTU7#_Ar=?B|GkAn4PsupQm9IORAby8_}0Nj>TkT?Su`v z#p)#6waAJ3}iY`~rUwKGimk3Bs-4U;-%nr;{y{0Yonr9x8Jb)zq3_3CsO1Jap>_Q1p!yM%QH zx}$_L1^0*DXZ4MD3AM(G`{4f-nDi8T4(d9{-lT9>$~+$?Wwxihv#>;%T^luVUOFs{ zTykL2Kk%+~TnI!uJ*!XKSYL%yx2?snGmMRaWO+|48x)zCq{E(c^wu)zD?uAb|DgFu zxOmeh~8=mG4 zCF$J#VNU0!DYwHUXVNj5l^JH|Vo$t1VDvhvIy%y8u)8gm3i}!+cd&<5)!}x>XTlm2 z7Xq=zOKQDXU1fAh{Z-=@zFH&P5iE5rKXyoQsT2C|N|@b7QotWzQfU+(R(qsdIkL^_ z1Cvou+)B3uCYCHj^yWjbjxcA&NVi9N87;+~1d}qcf%L}(LF`HWcS3fHbbRPm{YeLh zNygR=M7^W)GX1_w=)`}!ZlXuI{>$o`1+&*qZWg>6*27w&ZW0p5?0swO=vxDQoRaxoAk>PK>{R%&vsWjN<2Jxy)^^u7A0`cgS3ToGAkuy9MWEKhHnThIK$y%2 z_Ovt~CdsV1-*?=xWE|Iz^;Vpy7fwm^Jvi~!<|;bY`y5J^zY{3!ahaMD>#a0NFMKr7 z*K3mfC8M->$hIwPs^8atvd1%=8`uMXC(KFKKGt^=c57S($38;$(<$s=o+BhR#c*XT zehL#Sx*A)yGE?-4$6Du<@K`@Vas6vq1brzh)|QHJX@`rf4DNFHe?#V2N&g!O{|}|( z{^iLk9*CFsTG{@;C`)ofFX$ptcb`);M=F?=(E8jdi=$zQw>~1pj%D4F$(GjR`8yee z4GXD98gwv_&tU8NU!>h2e-UAs{*_)bW^u7Te6c1uQCMP zWgyjd4T#21~XUwQ?^@Cg|_Hm@-G2P)a9P2x!#6OK* zqGmgG^5{iAcSWq1ntyVtZXg@|uo}VD) zbEg#jVMi}g%JiwjManS$94V?Zj{fhY8W+)5M~3Lr z^J}&j^SdOSsL1&!jp3u~bL zXEXbs&8#zI&LRJ^nU%^Y&JrZ6(0?|wR6?>-8UNYLdj7MS{mad*tgHXo%>MsqGh0z6 zzkl7t-mjAvjBoeQBkjUhUh8T)j^0vgX-2U+M)$BL( zg9h8LOe?6~bl#Bx+r~6a`eyyj@Cofdxz=E8|C%~9uS&NPS66mRxo3I%1(V1AB2YPBRuh3jOl)$|&!)wS=HBvnJFa;>R1zLKOzz8b2lzZy^x zI{nooUFEegusv>*+mQ@6r*kC#m{+GS>$B5Z6c@`9_ld?2S-8=Z%1B zqzm6jQjK-Yn@K84&*B=b&vI>|%L1yo&RdqGJ1-B_ zH(@Pxm*q+NI&9_gfQr>OU`tno>Xa1$6|a}ANYZ`Z3e}-+1yq7gek)0btPIs#VQsZ< zWs=?i%UBsue!USkaur^!3aIuveHC7<#w%C{9kx12?}klX9Z;S09@wO}X`QzN>Rvth z?Ihh`O{hK%>!Ksq;2Uhtnt%%ELfFiALUr4B0;;>7^-hwGTN|n`!+PrYwfG0iUmH-p z^hMZ$ck%DtfV>p?F8-~j1rmYl`-5NKylJD%U}J;|4t2h-VuEDpjX%Oj1MiPOd|B*rp_vrpIy}ruS^ZtIc?| zIiN=9$(!+N3tqv}b>tSjg3Z|yP@{AqZ01(H+8R(9de&CF+J;xKOdY=suVDGx0&1+j z2wSinueJwNw$9s*S3B?uHbHmUfmg7VI|97>b_2F_CtmFg@SJwpPFn3fTJ606uN@}8 zN2|S0tHGvf-}|&0EaUwEZz*nsjr;)LJ_x93I{gD$Z5OQudqRipqSaticLmgRy$3ew zL;U+Npl0aFAL8Ff_y?P%BR|4F*qo07^3oP;=5GAk9Z+-htljvx2mfHt>i9kQ2g~0R zP;>P~*n++Iw>O})&fANB`|uAoPj}gef3TJN0?Ozcu%-L)Z-0OnC712TzXSMpAfR5< z$p`T7WBh~VYv0HC2g~?4pkCG+VIvRX-@$-dqSFuJ-zWG7dsT;hf`727p9IwFdJk;U zA^bZOP;ctVhw$$({=t^%$iw&tn{zmzR_H?5%p>@BB%oI6Sx4~iDE`4#>-eMi2g^Si zP;2x>*n(sDcPzkbDS5~6?^FDPtKwz`wKj2Ro*_oW(!b%CiA=T;G5#J%@ki0;*6iJBNQ?;@_76 zby6pPiGN?=AMCXDeT9FpjIRQ`47(9F@;v^X52&*`{XG7CjeoE&b=cSV2b=nJK%Lin zV3WSVzi$G(@;mt({JVgEu!}nK0{+3~TnMP|bRlf!Mf|%MP?zzB0B7Q{DV#XJ|Jrv zY|;<-_k*>j{eXWz;vdYXBY(s{*qk2&vaZ2q{uBTH8IYCjpZNC^{=rJ?_@D3(mj6>g zRyWv!pYiYKfUIvn$3K-N0g$lvhqH*2l?4gY?}KUf_d_B;N;rv4s~)ebi4CjQ+F$a;4Z z|Ng)~Sfq~p1OH%i{;*a&*vvoi@6Uj&d4DF&i^I>$uqN~3Rnoi*Ds*1HV%3{>Q6-rL zN`;#43f|o0DHNT(C~k_PrRm~Daa|NEy(nVM4N)vDf+D2|ig>fE2#UTzC_;l!B$(tN z6d}Q?l-U-fx~jIu7mQ*8gQiO;itD0S8Hysw+z`dm zQYcbNp-48%N}=dm8bxSn6#Y$dX%r!4P;3=Nit&{}u|X6WWl#(<8$~g)EQ;!7QKXvm zvM8#QLvcV9LrqvY6uU(+wH%6JW{)T)l}8a(9>oYVxjc#n6;PZOMY@TsfZ{Vz%&CB4 zlqnR&%!(-5Rz#6uW>rKHR|&;sQDmCRfBEJ%fvF4&E7F0&jy)ueylUEr<=PD>} zieiH4QU%3zQLLM7Hp{|L^sR~_v?_`zCb=q#kZ=@RMKRU*!clAx zMMgM^9J5grBdejPUJb=GlU@x)mFg%Ch~fzoRvpD|QB19lV!GKQib*w4MAbks!%VJ$ zqCrg*r$sT#MAk&{nJDJeL^0bGiehFh6m4svm}6$uLJ=2%;<6~7HSrNBE{GyO0>xZ& zQ4|Ymqv&26g*JJ$QFN|@;-)C(nJ#tMYkUz_!R)A`YSB&4)=@oGNuQDFz~v6D*NL-O~r8KXTV_?5VnWb>>PO&vDLEme4MINvLZi?*_8eHo+plPX>+ zN;df|)oky%K*7LS9G$u1`Sk#EgS!)XBB&b13 z<(tcG)SJQIjNmt=0`5@Es;o5YK0Emdwkp1zEGX+&rbzHLUa%=4#n@gjx`TSKyVOH7 z-}Ca7%;On6-|Tx%waNM8Px~Xfq0SF9S_mJPOF_~s4briZrwqd!-7rTd50%_!AHyA; zJfXRVuzch(qXgxtPIp_E;~D8Ftp_2t(v$A!rDCFlbWIJ!}ePF@>n;OIs> zI(anG(9vZ$x{~NxIJz;Gjvuc>QMwPSGaW;De&RkB&vJC~yjEV6kk43jQY-RU?K%+8 zvmLv#ge4#OjCXYMm~D`wo8ai=DaK&yX%B&i9c2Z=>m9?1NXfV&SmNm9*{cK@5}s!r z-J_09-co8sSiGF-=&BGd=GZ-kltPDri$EO8$#o3rIG*o-e5N_NaKe`?jmIO8cljrO zwdy(P=$>$N)#2{z5>Gn18tAqV7Kf%gx|)QyIl8BiIG5w8h0=Y-|Fo_2M4=7o8xvHVG*^@OxDcj*GUf&l2|H7Dk& z$J9cTJYOaF9>FXP3^V!jRh<~A5E<&y=~KZF(2G>^OtmMt56GN!4`>J4oA2kV%Jmu( zln2f=DN#LSC!|bM_kzx#3+QU1jH;O@%utm)9Y0f~6oGJOq+KKhPfx z0Np_k&=cGT9ss>TAJ7GK0|8TSf$A^kL|D&=rJw#x_!l70vi(4wvqys_AO^^^@eq(X zP3Eo27^=}Kk4@eeSkdcm<%2P5u~pRoZUYPJol(I5-N9ffe$|ayfxf zK;9M{2o{lH2TCaK2ebzA{(!t$@G$xzAPMvZ8^I>98EgkTfQ$#}>o0(5pem3lEfoAo z-tv0ZW$+a^2TrGQ`5b%!-U2JZD$tP|wgvKXg1orU0t_XS55Y%ZH`ojIf%D)nI0BA> zV_+VTvG%w!0~e}>IUkbeIv~?cB6+n0hlsak8p3A?e*r!P$3Y=D4Hg1pMWd^rGZTHGO0^C!I$6w{5S9i_!G!{d;)n2h>bWSg{#mVMMY2v z>_zboco)b#S`NsIH)7~wGvQ5O7xq#pxlxugXKr}I^jM^7wjNZ#lrhajyhIt_B>1%QcxHi_;Bg>> zG#8|UkwB)jQ`ikdN_UbmcNM-LNY6Qsl)?KY_yQDy&%j4Oe35bXKG*_eVsRUCgluq@ zqL4zo2o{1oV1NeCgSlWdcnC;l=|IMXgk^@x08_wtFb0S|6J&#NU@XW26Tl;25_lL) z1mk3?n@r$2@DDHtJO!QvPk_e(CZ4I_G4QApo`%c?)4?-9>}G>mU?!LW#P(_MESLvg z0Q12D@H%)6ERoC?0r6-tcnQ1=@}2N2$XCG|;9am5NNv3X-U4gD+h7@34MZnZyaKEO zGIa_U{W`D_Yyj&)0m#|P;-$kJ|}zt`7t;IJ^}8H zERKIv% z4#*5IC6^kgKv?>LTRWl?J6Y7jfD}T))f`?ASsO^cvbBoBNGXWei;Y0`n^NdONa;h(f%J`LvIcG^!d+Bb zqLgvj6WJa3K?@+6NC(;m#3m861#Lh)hy}6;$AQ*BMuaT7q8Hu0pd)Ax+JSpOC(tp6 zO9${W3EbgvH(bKqkez|tq$}tG0-y(wj(9)#tBxqOAno4^{7U#=JL7%m#YT|xCl|M) z^&=t~xWgoga33H|;%4e*_zi05SPufJA<0x~=mBJJu$b_jwbU1#)P~F#l2+36m-d&c zZ3amN(ryB2Be|)JX=!V@i3}yzb~s$(rS_(R3@{pu0uO;l!NVXMh;9tX1l>rMg&YgU zf$`G*69`NO6Tu`Pi5~$|z+>P^@C29+o&qy~G|y~g067o&0(c(G1^)o@qmlIb=fJZ- zg9~qP;nU_zTNZEAzga7@=XDisF1)UOXyl&H<5dG=qMJs?G`Ch59}CUSatS{T>h}CT zVp>GUG>vX%zI#K3^SfrTH&t_Qu-CMCQ&kCH?6uFT`uy|l`74@jjSo^}5|6#-9h3Q{ z3Tycx29?O}{=`ojRjXe1&D#d2h^atKm0y32xqok~VYg$hnXM#kSY!`<^c8@H784kLK zkcN~^Y_vhWu>ZD2Uo)4?y=_aFx5Usryz+tdA?5C0-Sr)}rQ_L*ox!lBd)(&f*+;^* zyz+@Oc(Z6a10An~^*uhfVA)+4<{Wx&zugt0o73e?)N(v@Pw?EI_gLEEa&M(rNt;U2 zH%%%AYOR^FTs2oa%xYN6edJe)7O(V2?M~ZQANfZGmDn~mTJ}bT#FQmw%Ko@_r~h>2 z`0bc)%}tWF@|I-6#-RJVAHDHK=yMOkv{4str=>ny+!@I$Ee0#o6@sXnHh&}Tcntt zZ&61%X3ZK^KEl4Cdl+kM{grXee*5H}+tyo6KGxyx>8;ft>8Z{?dMx+0!H?z;2Hw)8 z%q8y25C76crp8KD&Ubftd#Eii@herM;;%x(sE9Td%$SuF(LI25Zj*jd>1J;qLjUFFm{^D*bTqIP7AhTS`TJZ?1}+-J>eF2eCGPe&{1R^A}I` zs-Q}y)hboXTfLI$yGk|lHmGEtSw$h&o7Y#V<}Lr{1P!XNy`YHh5v|`Pq^9m^*25=7 zi*6C!s%cCY6S|sP_A&KW)5CU}{;+WOIYj1ygQXvv+0B$u`^ZST$5ZB6F>sG;eJ`iS z*~~MW2Rc2r8Ec2R`8oA-R_bf%qTc>eM))l#88~4&C0iN z?4(*DX5F8cekfjbZ#`-J_~=%2)N`iE8anDo_O^x9L&JE^v5$L%Z>3$N_xOwT8a{63p0wL` zpPD~0P*z7QA7bB^?%3iT)hygSS?+Y&+_gg<3u=O=Qd7(&L(H^yNHxm5_zs>HM&h2SchX!MHhHnUhre6QPa-}tk?RqsOv-vn_^p|^UUjeLp2d6Q zxs(TY%+CJcb{<9UGGDBxj@{FFXTSVN^X6-gW!|>9*F+VNp*E=nWcY@eQlPqfYcw!> z3skpo_r%qnD-TV)d_1hBS3O1_m+qNvVm4sE&IAzQ?wP!$Vh(+^@q-pJcC0;v^u8Pn zyiFRKg&R~e2IB#-caOjw(K@lm(d^%OLO+mdld4~2)JF1MW5N;PI~&=P|4S7@$CaA# z)OyL6{YG@0=dkICL96qQ!QgT;>aBYIktZ>b6^c>fp6c7+`_HdtSH4z2Oe?$Sp2p^- zjjBp3_kiGCRkM!&lo-|#3#a|vBZE^vJ$tz5qi1{Fj;Y_+Tq13?f1fr!%GBCK?(Q+e z6~>fo)_lqJVdO!%EEl8gwQlq8E6Vy?yf(th-C9*!H!)*K8~*Rh{-9a1iLUD&L3~FR zPNzvXS2t1LPC3KfvxzezYYbWb!jPU`B`(r_o)xC;W))V=J!ANsuW>=f=te)@cC}n{ zGj6jQPLru4G=+Os@ZqFm=g$1_+zYo2ZA*ty5vZo5DIeeWMfo^vvy$tId-@33IjKUk4^hoI>^S$W%$RpaUm5xm$(&Bus^0wV^ac0S<$h|>$$NfzIST`) zTCbbt+u3ioPc$R9GgjU6kBeVSs_tL>%&)g|x?m1&=Z-&`i(((u-qhGZ#%5wBWq*6dJWb=;)xnaRo9uLLjp{IV=>&it{}T*ffmJu~^G<I&3!#%sXN0awn3ETUA1|o|-x#IPoLtNK)05;=D=y0P|nW)X(VgL0!$;AE+wcie1g# z4^*yNRS?*viYRYnH*?>I=;OPYPxj-Ldzy0J4dE3>pJ>&|DJ}U8GWj2J!@pjPrQZ~o zLmzTOYcdN{yG+fGFn5oSel2a#)K|J?K0tob(aG;?v+_88tT$)(s>UIX@~T-vD%R*G z`xr*<8P;Q`UHa$u`BR5lg=r>hbhYm0+D8mv$Gf|_n+2b#MyB*GUdEVal6F)5Tg~>} zYMr<7ee(-dx2RjkU9V2ul-9dVEwYmB2wl=W0Q*L0?R6E~ExzWZhOh2X5#&>LFSGLC z`|Z_gaO>ZSzL-CLfme~p`ZxyXF_5nrTe=N=)bmcCJ!IY7o^-4h3o{??RaI?2o2#p) z`iWZ(dP{USUH35?|7q6Xuj*~~*}|Gx51K!v66*H0`&r1W4#m#A`bt}}m(fNIHtB6z z>?idm^WuJ{0J{mB@rqQD1An_~Dlokca5sDN6ii0{(g~{l`!;sEi8rRNxpIK|?_n}O zW)ofOV^!7Fg}di#|MtMZu)@!u{+t3kt!rDe$(t)Z__%rXW6F6x+1}&6c&+@3_fO@8 zTGiK78adT`Pv*P>R^p)a^nUyxMKu@mkA8Ynt!-&mJy;9um&T8QW2bCpo;j$hhPy{~ zznHhT>e!48B}gM1M;dUw*(qr@n3D(Tvre~r&_sUXjxgDaQq1n^ZF5G%3KMmR(z<7L zZ)@{r&d(41oK23h0ihBd=j`EWRvl6;!rgdW5p)7t2?>qEEzmMk^$B>0c?##P*A0M{1VX~&< zQ}_{eP)#!59iiNNO#D%NdctIg7-^Oq#l)Vc`I>(0sOlc>p7lNAaFg|4O)op)b`h?d z?Z;@|KF4U@(rISgG1ainoHV<@?up@_g+9Jm&mMZ1R8qHW@aIbzsPF zyIQ)eh`#UPcc#j~mg$vh8D*aRlooSOEZ=mf_C-?iso`SRfT*qkPBzQq25owBB{ zsA7DXBe6A!RSF`P|IK+!Mn2!q>|q}69(q1+)7Eb5tND63Re*c{y%}z}Go7jPrh6ep z?`B36QuI~kMG-0HpeUUg^}m$FnNelJx&MUfMn8D@1Z$Ifcz?>kt|g*An)C`_0$mzx2nRS$fyhUW;g>of-A%#G8`=sis;-`Lr4P7#r5=6z1wBW8~X z``dg=_ki}cKkitww@k~C6h;x9Zg9OA*lN zo@FSw=dE}A^!>cAwpWp1)xzGAx+k+g@Li==eI}>>L`-vHaQ+jMaaMKm74p-Y?5>WR z&E!&uP7`B;guANm?>bhsVzhBrhrfjKk2dx}szwMdn{JtFW zm1%rV-EFeYsirJrOU|j9G~`Z1)nDq^yRI*v?|9^ZWh&_}%l|&;G8@cYW9J{jO=t z-rdjQEuN1zdFDn(e!inz>G?(1y!CDK+|*sU-JUc3qszTg=jm?m?f7kK#cjj3HtFkj z$#4F=n!QqpTVXjP9R&Ns3 z$w)v}Lxv%1B7Y|=5y<0?+=P_;#SVWQDHRSuh9k#ij7S?m-U--6M2gI?^2}_V+rn6P=()mLV)sK9D~LE*;2Z97JXyrGrEy(@Jz8 zt|d|Y=f>=RZpcQC*2@Z&$gEVyZhkXT0=mwTqsNa*ayPm~J;*gnjk%RXQFX6ac2bsF0h z1Tu!FPI^?jeja@>3Y1354EU9TGI!G{D2uEYQaU^&#^#+I{Q@UaX&F%?N2j}7Pr$|Q zvnF=K+mKSP6(JoLRJQj-C+0&_GNLA>j2)To@byjYuE)mNJqSmNtM!pmLn%it#ZL65 znQb?L-b)Ck=_Nt+GAG2_>?cM@0-~DRvOjv6iSyx7+f1Yc_5<|7M>sN2Te4G6H%GQZ zN_~NP{<;3V1Z&sJyxl-a+>&kurpmW;NII~tmEGWkp=kq$()F~A)QPFc8|Y`S!W z8=W$4XcVJ!h;p*TR{87>yorU0B=M?$X%QabqW;PaQipYT&3rsYfU;`8%C@a*^Wda!00) z#42s%kj6c1yC;#wWqF?OZW{(-_BsV5X7iBJvFS*0t;&5iADF`b4NY}zgv;QSy5Dwo zbX0nZ^z|9I=r1BArl+0!<=9I-!*D=?vjiR@M^pw4NKYSqz|IJVOTlsD2S*LdaJd>j zX!8tYdGx>d?R_KEDfbOrD&9}U6_6pl!w20k7s`VoEX4#>R* z+hj&*xa==O`r475>vZU6czG!}1BEpBLO(kKy|gE!p7QCKkcyfAJcXw+<7J%FMh;CK zn>H>ZZRFq)X+wsNYszLWVP!|6OWYZ-ZA+a)QpOLFwKisuU2ZT^?ADRb5t-E+F40cG zn*r4ECVB}*J=Pb_RL**ughXMgBdb%nR8UQyp?iVp%bH806<1)o{nad~jg?d%hLl?D zCG2tq+zdu9gJsVSS{ZJ)zNx>xxvxWd$Zy-(nhagCB2Y+$HBi(<7EQM+t^k(?MvNMi zlEJ1koI#U1E-Gs~gi&m%eFiw1J%lCo<# zOv-MpdT^k=R8qF?T~c;^*GbtW?j=-ytG+p;Y`ZT>*><%EsI418%Icq5qw{O{f?^qv zrutIlgrM^*u7|ADy@a)wm3o@iYy?g>(M3r*Qp9@J5_TI%dNKF^0RPQI){dQG_3Q>N@)Oik2jb$u#F zXLBv9^XvLNgW0QE*aI2vRm*i+J)isQa(Y?4L{(GgLw+o;8`Mu!i8`&m&ohNBSFDRz zb+3mtgB2F$zF0vwh)h%sbXufOJ)*O@zM=CYeL?jrxm*wEbiy;2R7<@wJi+~GCB3Xc zqAINO8~9X59of*Q7V5NyKKGe0y{uuPs-p8z4bYK|e4h1{86cWbdQ4rf=MPv1SdhL_ z&#PwW{6;?aN8!3bRHAa}v?!lS(AiwGb$*o3{Yw?yAUaWbby~E~GrKCSTlK_5dEGmz z>I-BA>Bz=D^?**}`ijnO>@dDyUQvs6-c?lw|(3*oh73@M?e=*U=~duJ^@EH=?oua50) z5lx>xyJ3j|-#x)~ZDxhv(*br5d4(h{p6UOPw;9%syrR~ym8|D-wT1=jH4VI;kq#@O zuS9#*yE;40=lKR*H!R$u3yQ7JTGuP%64Y>=)=UN}yP3~(7_Ha@NzYWQj`aG}GM(ln z=#hGvH_;Q*z~$BxAWXD7P*ES+>Rtf9-*7*<@zM0-6yz@%IDylvdb?y}7? zV0ZG?!tTYA&4-|bMA>=DVqIV|LxU{mX24{~i|8?f<5iSi)*{gp5^Z=hrfD^J)N1raq+r5iJqSwdwa$-p;p<$?GO)xi91#^L7%|7=u3$S zvN+rLf=nDCu~zQUIK8Y*qNgGYU(8*4O$)E*0hmP0u4*~Vi3J_G4il#spG2>U)A{%M zJmb7})7GT(tbmD!R>$3^y?R;OL{AyICjBR91T+gKl?3ZCP2+MAe4eA|q%qr@vK)cJ zXpPcIFlpNwbv0W@cJz5pJ38B&DrAcVs^?%ZO^RlVN$a_9Ci8kk-eZO z7c>smT1Q1Ccs7%gGPIxQ4XR7BiKXu)DfISmKMm_}o1KK+9uIef&)RI0b#@nDP_B>e z>8R)g&o88~V_>ed^Lk=gU$Vp)CI<8gk}@PgdJL;ON9X%}s-BMQ>hnx!V-H`2Q5 zZVQv{5uLVP&vP*G$X+PNU=m}ivq2TwvxxM{1__?Nr0g=Xzx*90F|o!m=&Ws3FCnNE z%5GK+=aaHy7}L?~`2xmdr9~-Sj59};ht;BLtJ8Y=Jmb-^`G}5?ErCgEcK!LVmO7mg ztHX+xT3P*Vyq;v3Q%|DT^E^xzycG-28Ir85tdiEu{I0XTfZ45>IT2m#A;6M7A41g;5DJPR5~QQXocSBE6m`VKPnF1L@-qm>mzXyaJO^u@9>#CiCqPQ=@cRvd{B6 zy4$gEAM2(sBqs({=q`KBN^e3?e^TwN5WXoXsw!kT|0|3&EDP8huX;!+&pdV*>4-fP z`(a{_J8UxLb$)MOP>-HWCw+;T{xm6Z$X=3%U@`<&xI9t!@y~6m9&uq9jNK@!w6zL$ z!){L?Px$?T$t9M(VfG*kdl_b1%G9|A6W8s9-QsU{Iky$EiLl!fAZUx^$v*43NvbJj z?1QL@&hF#$On<;GX&-HyVa|{xdfmT0pojHM^u)8d$O5!xNzg2qU$$w_K~l1tus=t6 zgKBUXwXpOLlX4b49bE{cT?sRDqE;{Na_lZJw$oq(ZnIM`2_a+4Z1nZE%h@5^1nX~G z4vi0{2ErzOupO_`*(pBHHFOdkwkno#;=}gH6_R+U$8_2NpJy97@!sCd3O{1U&)%6j zz@#)M6DPs5Fo}Y_Id6wC>#|B%le$hH`)IXyqbFhFj@`*qFezuvfuM?gIijq&F`85h z^t9E;>sba9H-oK!6zON*!q77Pz7Hld&ffVJ!6cA&K#s#?{@GJMfoRCwux|~f!lY#m zBQ}72FlU?}i4RV(Z`!D`qc^BKtdrF#3oR4ABpj*bu{rdpjAT2Sd3IEhjw5GslQc|7W*TXRJignaCK6p@IQp+e$fk~~j z%RcrgOdPiMLr+MmeXbEU=23sxy_V$~*z2%6gZU*)CcGVtW`hF@WlbHgX9298-9nUC z*B?<_uWQ@X({PC05(CHFO@rBU_gzxlO36fE$$bU0qaxFy%uss=3$gA3`@qDKgNT_t z2PUmJTLny(cquJ?ZJKs_Y7UQ=zek9R%&mm@!Vr5jT*GWNzB0cdQgyI6u14zoQ9jR7 zbmG1pnhP-7eK{l=4R^VGyg|cZ-K?W3my`@6GoGb)71jl2k4dW$ffa(IL2tkY zS;tkG^xOR-06k#0k1O?*&K}D@{?JLSEPI0TD~x?W<~B30>qz@}u_x7Jhp|UtxfCXA z%nG^ZGE9!8V%Fe#M+IiHggp&rhn?9Rv`Cm<**3wwf0S-8KGD;9v^{4yA8>0bOpNXQ z6PO zK3ThX&}%UJSpCY;+c$BQ#@~)O_f7Y~q!0F z*U*Olx^mW-NcX3cb%V?n znISIg4@_MDQ5J%ST3TBw(j^=&vLdMC@c)L)w5s@TRPeuDzAPo<nBp_OIZa_T>_%AbK zDUhE?>0!1bmm%dRQuND#L}Zo2S37(iQhxtRO8NCbBC`R=gvk7Wi~K~2!A2qc?v};i zp8(0<3FLRTl#22!?Z1{%ez#*MvZ%{d*R|hK+%3iMfTOphp8tfev^4XDqZO(2jVB^{ zi{h}O6&VCh0EyCRAa$Jq^7}I>`DcO1b3lHU)af%K+62SC2NJU%fLQ$q7*wsTFd7aL}H^P>o25axw%Mm ziXz3{yQSpMMlV@UJ9f`Hc6Up0M&6wg z`J!X@k|P&5_IJr)R)a5-A$hMj^6!qJNJ%boxJY&Z*PBRbU@20vvK_e$DGsaabCI%FZFl$%q|A&xNco9WI&^kLD@dO^+PkH+wcpW;l(xQbxJcO! zP9jD1m81VxQtCU6odo-wV~-56D)?Fy`mNa!nWael0u#lrT%_6GkutrDQ-|n79a%!^ zSa1Lu?%EhiETI+$*6)9e`|~KpQO^`pN`0s*fw%< z|4d4^V#pVhST0g)Q%A-*vYBM^6Dj##N5(sPk&;6}NxL{1{OAGT-T1?K}8=pI)Q|I9W`i(wNKjPH(LuL0>8+z!Q zY9UMKKBFG1-T1K;3l>&y@%f5<&qRNHAIg_ZQlg??2?N4}iQ zJ7Ckf2I-?OC+j0Ghw4_Z_*GFo`;}xBtj}=u=;nVgMkx>-cv<^`dwDs-ez*Cs{SpZI&kUPSQfI z(fSJ4#=3KMvhI`}s#j+FRg5lxU4!*m=H~^T>}AP%>9SBAy4=rGzuwD}b+6^2dK1j6 zJu8xR@QP5KzQV7X>s;6dSk;w&-iAwCnXHGd4ApyKt#sJC$-2_Jp?cc8e%?9GgYAMv zt@5ijdeSPqT7_4zwmNckvaY{6RL@!MSMBvt*b!K(HGbZ)nY|`i&sr0zFTpzN=I`O# zd-(RAU-@-D>^v-KtzRYSg=>@bg0-Rg2CTd8ybk}?;omyH>ZuE0*I<3t`_=tAdp-WG z$G`XeypPxWef)bL|6s}5lY@Ub_?P2Xy>)I*vU*6D-jJ*w)@fWH(ObFp(P6pCs;?fy zwV%$*#j{*I`@pYK^rR1xd6{rO*MT~6W3n2gr*lo!M>pctM!fpauZHN^AL7-Acm+$- z%{SrICcN6@=f$^t*m+peM}C#A7k-3SAK?{jlcj4bI{M+SM&**&Ed00}OU(L}A^YAYZ|6tGS&b#q%H~#JRt9iNrb`92Nk6&q> zy$ApH;NPcyHDCAs6#qWOKbX;;z4*5m|MvQMX)qVI0ao=hKW|#5eTILZ;U8>~4*MMc zKF7b${pwYn2ipaU+UHkG^rU_Gw-5hdZ|KPV__rVb_WRXa`Y7xOtknU(dPmPbfPV+@ z50>-iPt;F#f@EwC4!^9l^gNewC|pVH;pokNVX{opu!ej^ZC|lMXwE zf5-6em|tzyd9YousN;UMRZlvOf5-6;woON#z`qmtcfzlB=%cVBuvRDiYNwuk68}!( zA1qHd{|f)U!oRQlYLCu`orfiz@~gdi;VJw(g@3Tmb?4LgcN+gr`_+D30J{e3bH=X@ z>g+T4cLx8?`qdY@_gVZqi+`}g+H(&7&f(uVzdEXOVH;pozxJ!+I_+!x`x^gXCw162 z`1cL|edAZBbRKLMEb3doI-@6ji+|tZAMBit{0{%V!@uwR>KlC&b_CYyykC8%XP?Kv z^Y{nL*Uj_sFCYK%{pzC5hn!fV>+`)| zUDes&-zEHm{iZ#a@$WMJUG}R2oeSFltNMdqUDs(p;NK7U2fLxe ze#E~Y@$W~!`<6@Z{_#P*3mSFBuaus21qZL-Agqv%{0Rqt!oi>Xa;U+Mz*=3k4z;T| zcohd>9^L$B9Q+vvfA-7420IT+`o%9t+b=ly3l73c>dwF7;IBCNt6z>c*fm(6-~4jG z{f2|T;ovpD9C6oh@EQ)nDr!#w4i?~GfnSa}*aleD-~DpX{f>jb;~=c64!e$n*KzQ= zUk*FiE?Cqb)?xPt{{4Y}uv$9u2L9c^zZ-rz?qEk?t#10|z`KcmH}MY^shi)zzgzfs z%R2I4=Wm71Pf~srHGiQ>p1(ka&c6X`Y&t8IY&t0wYE~)~F{VHi*F@3BjUv`$yHPB4 zqX;d8BF^+KgrZj=6q`ihHJ-vKf(xTaFN~tO$rZ&0QB(~=kzmq-Pz()HCCq0*s*7r6 z!iu1%R0NA@MX>OhJW=ctMO0A~ZOo*iC?*y~aZ(g*O=K{N`oSpX1fytgj*8-lC|Y?? zbTqR)C}w$3ToOfR(>w%4dkyH#tl37>`#e!leZiu40>0BH|r{XA9 z7Dv(36o}%QDEfq=xZh-lqF5S=BD4gG2Tbo0D0-DZu}Kuk##53@a7h&DB~kP?xuV!0 zimIhhJZ#cRp%_{U#a>bLF=3@qR4R>PT4@yhOr9uqi6W{DiWD=c42p?mP@ELSKoeOO zMg6iU=9EQ|YL1HHh$vc>Lovk6E{9@PITV*fk!G5gM-g8h#iH^khMRm*oEJq>1r+IK zVFeTmDxkO_iczL>MHHPXqF7lG#TZi{iff|iQwc?e$*zQAX(be)VJOC%-eD+ug`wCa ziV4P38AWhq6zP>wOftEm*dU6k;V7nkyHc49J8 zP%N#5BD6Lkezvx%t_qozwN-Z&mUE-Fx~f#|oGW#aK`|BhleJNGxB;qOxp4XFJaOUq zRMx-|Y0>f@+xj6Mwjpu6H z<)Rzgy%C$yDFa81OXV3ce*+FNYihI2Njv?Uso1yjTT|*p0>mi3@ zIMmU}v!HH{P9921(gW^ubi*7SgX*g1=!QEwc`6s_=tej?d8ird=+Z46e~gxAA%W-E zBOOC|KO*p?e3YY;KU%*GmA*rNU69yc+Jtt!&gbNAY9Kmx+#vXBDy%z;^kCFSBZ2H$8H)@Ivobi z192!*Iw1K>8`lLOzbr==PWqyyv7hgXojl$+=I9=G?5e^KI=UwuT{ZYd(&EqzM;AeQ zlcReQiF28*>L}&Uo$`~1!{Tuba1}_W=Ae`8n&1+UPKoEDs|C&g`91IGYLnhYS~?&P zk@=tXH0oOt(g9fn(neiyP%-}Un~zdLQxC|y2Gx-U$^TsSK?z4EPn|^<2}(J-g^sQP zx-yPV9!ARwX$Uq0`N@N4{wFV^Tkq0{Zn1=48jb?jC70i8j$t(Eo22C#*b+zAm~=4; zi0*YqcMs{~q{X8*99;})nV8b~Hyxckb1hF=I{KEQ%Z!D*59If@qijk#$I`f5?>M?R zczGI@js_l?HzU2Be8~$uKKGKA@JpUNO6PyB1rlC?@RE9r)1jwP2_D&l27$U}zEQOvlvOXQygx_*@<>!3lXe5$ zfow(Xfjo$94eEk=pgxEM4M0Os2UMenwUOItAGs3j(#4v@_z z(xfa|x==lw8A?(n;4jEufjoGYN7VAXJPJgE zdw}c*X+SnB*^~x@AwV{&exN^)cTpY!4}cIb5ljNrDPIf76a30xExPr9>5}PMLqcAk zcn!$%mF4OKtw9@bFOXMg;z4r|0o2feS$PqQl?_I0}w|FM;em zhrlwBEzcK+k&rh7d7s{TALL$oC{Oj919|E%ZwQR1p%fr*<0OL(AQyZ9J_4J8OmvyV z8f1YmAbVADaFe>_b*%5fIdBHZOJFBcxSRsZ!3wYvw57q8Kwc@3*A3*=gaK5t1AGE@ zf;_Mrd=2)41K=Py1YQKPh^B*$F7x0kszK&D>RkooZ3Ouf?>_Qm3%Lcp0;j+i;7f1> zoB#{KOJD{#K-t}3FZc|64t9cFU_E#r$S$xNya(jPz&XmR>Z7aq#kY*OtK5;41B-~ngKZ&WG|PEzcG*l z#l$RD;UTxGlav|@o8F66Y-SCTVlAo|N5&%Kfb1|GK?l$tNDGOe6=(^XgLu#aBml{4 z2ik(x;9k%MNVy~+yP51*)j?0dj#kYgJs^Jr_XFAD9sp9Hu!($?J|>ftopQEvxn_Zx zK-PmS%uFy83<0u@9mj4EQl^lsv&-;3KxT{VDzaeDf>YoKI1D}k;>!;3G1v&QfirlS z)_i^kg>>R&un;T&FM$`pJTMmw2Wdbm8wzACNLqHK5nwXN0O>&VBf(fO28;%yz&J1o zOaSA-qq41u!9?±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 ( + defineConfig({ + input, - output: [ - { - file: pkg.exports["."].import.default, - format: "esm", - }, + output: [ + { + file: pkg.exports[name].import.default, + format: "esm", + }, + { + file: pkg.exports[name].require.default, + format: "cjs", + }, + ], - { - file: pkg.exports["."].require.default, - format: "cjs", - }, - ], + external: id => !/^[./]/.test(id), - external: id => !/^[./]/.test(id), + plugins: [ + nodeResolve(), + ts(), - plugins: [ - nodeResolve(), - ts(), + cleanup({ + comments: "jsdoc", + extensions: ["ts"], + }), + ], + }) +) - cleanup({ - comments: "jsdoc", - extensions: ["ts"], - }), - ], -}) + +export default [ + createBundleConfig("src/lib.ts", "."), + createBundleConfig("src/util/lib.ts", "./util"), +] diff --git a/src/Trait.ts b/src/Trait.ts new file mode 100644 index 0000000..6018376 --- /dev/null +++ b/src/Trait.ts @@ -0,0 +1,153 @@ +import { Fn, Pipe, Tuples } from "hotscript" +import { AbstractClass, Class, Opaque } from "type-fest" +import { AbstractTag, TraitExpression, emptyTraitExpression } from "." +import { ExtendFn, SimplifyFn, StaticMembers, StaticMembersFn } from "./util" + + +export type AddAbstractToImplClass< + ImplClass extends Class<{}, []>, + Abstract extends {}, +> = ( + Class< + Abstract & InstanceType, + ConstructorParameters + > & + StaticMembers +) + +export type RemoveAbstractFromImplClass< + ImplClassWithAbstract extends Class, + Abstract extends {}, +> = ( + Class< + Omit, keyof Abstract>, + ConstructorParameters + > & + StaticMembers +) + + +export class Trait< + Supertraits extends TraitExpression[], Trait[]>, + Abstract extends {}, + ImplClass extends Class<{}, []>, +> { + constructor( + readonly supertraits: Supertraits, + readonly abstract: Abstract, + readonly apply: (Super: AbstractClass<{}>) => ImplClass, + ) {} +} + +export namespace Trait { + export type OwnSupertraits = ( + T extends Trait + ? Supertraits + : never + ) + export interface OwnSupertraitsFn extends Fn { + return: Trait.OwnSupertraits + } + + export type OwnAbstract = ( + T extends Trait + ? Abstract + : never + ) + export interface OwnAbstractFn extends Fn { + return: Trait.OwnAbstract + } + + export type OwnImplClass = ( + T extends Trait + ? ImplClass + : never + ) + export interface OwnImplClassFn extends Fn { + return: Trait.OwnImplClass + } + + export type OwnImplInstance = ( + T extends Trait + ? InstanceType + : never + ) + export interface OwnImplInstanceFn extends Fn { + return: Trait.OwnImplInstance + } + + export type OwnClass = ( + T extends Trait + ? AddAbstractToImplClass + : never + ) + export interface OwnClassFn extends Fn { + return: Trait.OwnClass + } + + export type OwnInstance = ( + T extends Trait + ? InstanceType< + AddAbstractToImplClass + > + : never + ) + export interface OwnInstanceFn extends Fn { + return: Trait.OwnInstance + } + + export type Supertraits = ( + T extends Trait + ? TraitExpression.AllTraits + : never + ) + export interface SupertraitsFn extends Fn { + return: Trait.Supertraits + } + + export type Class = ( + AbstractClass< + Trait.Instance, + any[] + > & + Pipe<[...Trait.Supertraits, T], [ + Tuples.Map, + Tuples.Map, + ExtendFn, + SimplifyFn, + ]> + ) + export interface ClassFn extends Fn { + return: Trait.Class + } + + export type Instance = ( + Pipe<[...Trait.Supertraits, T], [ + Tuples.Map, + ExtendFn, + SimplifyFn, + ]> + ) + export interface InstanceFn extends Fn { + return: Trait.Instance + } +} + + +export type TraitApplierSuperTag = "@thilawyn/traitify-ts/TraitApplierSuper" + +export function trait< + Abstract extends {}, + ImplClassWithAbstract extends Class, +>( + abstract: Opaque, + apply: (Super: Opaque, TraitApplierSuperTag>) => ( + Opaque + ), +) { + return new Trait( + emptyTraitExpression, + abstract as Abstract, + apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass, + ) +} diff --git a/src/TraitExpression.ts b/src/TraitExpression.ts new file mode 100644 index 0000000..9bbdbb2 --- /dev/null +++ b/src/TraitExpression.ts @@ -0,0 +1,117 @@ +import { Call, Fn, Pipe, Tuples } from "hotscript" +import { AbstractClass, Class, Opaque } from "type-fest" +import { AbstractTag, RemoveAbstractFromImplClass, Trait, TraitApplierSuperTag } from "." +import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util" + + +// type RemoveSupertraitsAbstractFromAbstract = { +// [Key in Extract]: Left[Key] +// } & { +// [Key in Exclude]: Left[Key] +// } + + +export class TraitExpression< + Superclass extends AbstractClass<{}>, + OwnTraits extends Trait[], + AllTraits extends Trait[], +> { + constructor( + readonly superclass: Superclass, + readonly ownTraits: OwnTraits, + readonly allTraits: AllTraits, + ) {} + + get extends(): ( + AbstractClass< + Pipe<[ + InstanceType, + ...Call, AllTraits>, + ], [ + ExtendFn, + SimplifyFn, + ]>, + + ConstructorParameters + > & + + Pipe<[ + Superclass, + ...Call, AllTraits>, + ], [ + Tuples.Map, + ExtendFn, + SimplifyFn, + ]> + ) { + return this.allTraits.reduce( + (previous, trait) => trait.apply(previous), + this.superclass as Opaque, + ) as any + } + + subtrait< + SubtraitAbstract extends Implements, + SubtraitImplClassWithAbstract extends Class, + >( + abstract: (expression: typeof this) => Opaque, + apply: (Super: Opaque, TraitApplierSuperTag>) => ( + Opaque + ), + ) { + return new Trait( + this, + // {} as RemoveSupertraitsAbstractFromAbstract>, + {} as SubtraitAbstract, // TODO: find a way to cleanly substract Implements from this. + apply as any as (Super: AbstractClass<{}>) => RemoveAbstractFromImplClass, + ) + } +} + +export namespace TraitExpression { + export class NullSuperclass {} + + export type Superclass = ( + T extends TraitExpression + ? Superclass + : never + ) + export interface SuperclassFn extends Fn { + return: TraitExpression.Superclass + } + + export type OwnTraits = ( + T extends TraitExpression + ? OwnTraits + : never + ) + export interface OwnTraitsFn extends Fn { + return: TraitExpression.OwnTraits + } + + export type AllTraits = ( + T extends TraitExpression + ? AllTraits + : never + ) + export interface AllTraitsFn extends Fn { + return: TraitExpression.AllTraits + } +} + +export const emptyTraitExpression = new TraitExpression( + TraitExpression.NullSuperclass, + [] as const, + [] as const, +) + + +export type Implements> = ( + Exp extends TraitExpression + ? Pipe, + ExtendFn, + SimplifyFn, + ]> + : never +) diff --git a/src/TraitExpressionBuilder.ts b/src/TraitExpressionBuilder.ts new file mode 100644 index 0000000..a4b5b67 --- /dev/null +++ b/src/TraitExpressionBuilder.ts @@ -0,0 +1,131 @@ +import { Call, Fn, Pipe, Tuples } from "hotscript" +import { AbstractClass } from "type-fest" +import { Trait, TraitExpression, emptyTraitExpression } from "." +import { ExtendableFn, StaticMembersFn } from "./util" + + +type SpreadSupertraits[]> = ( + Call< + Tuples.FlatMap, + Traits + > +) +interface PrependTraitSupertraitsFn extends Fn { + return: [...Trait.Supertraits, this["arg0"]] +} + + +type AbstractMembersExtendable< + Superclass extends AbstractClass<{}>, + Traits extends Trait[], +> = ( + Call, + ...Call, Traits>, + ]> +) + +type ImplInstanceExtendable< + Superclass extends AbstractClass<{}>, + Traits extends Trait[], +> = ( + Call, + ...Call, Traits>, + ]> +) + +type ImplStaticMembersExtendable< + Superclass extends AbstractClass<{}>, + Traits extends Trait[], +> = ( + Pipe<[ + Superclass, + ...Call, Traits>, + ], [ + Tuples.Map, + ExtendableFn, + ]> +) + +type BuildTraitExpression< + Superclass extends AbstractClass<{}>, + OwnTraits extends Trait[], + AllTraits extends Trait[], +> = ( + Call extends true + ? "Cannot express an empty list of traits." + : AbstractMembersExtendable extends false + ? "Type conflict between the traits abstract members and/or the superclass instance." + : ImplInstanceExtendable extends false + ? "Type conflict between the traits implementation instances and/or the superclass instance." + : ImplStaticMembersExtendable extends false + ? "Type conflict between the traits implementation static members and/or the superclass static members." + : TraitExpression +) + + +class TraitExpressionBuilder< + Super extends AbstractClass<{}>, + OwnTraits extends Trait[], + AllTraits extends Trait[], +> { + constructor(private expression: TraitExpression) {} + + extends< + Super extends AbstractClass + >( + superclass: Super + ) { + return new TraitExpressionBuilder( + new TraitExpression( + superclass, + this.expression.ownTraits, + this.expression.allTraits, + ) + ) + } + + expresses< + Traits extends Trait[] + >( + ...traits: Traits + ): TraitExpressionBuilder< + Super, + [...OwnTraits, ...Traits], + [...AllTraits, ...SpreadSupertraits] + > { + return new TraitExpressionBuilder( + new TraitExpression( + this.expression.superclass, + [...this.expression.ownTraits, ...traits] as const, + [...this.expression.allTraits, ...this.spreadSupertraits(traits)] as const, + ) + ) as any + } + + private spreadSupertraits< + Traits extends Trait< + TraitExpression[]>, + any, + any + >[] + >( + traits: Traits + ) { + return traits.flatMap(trait => [ + ...trait.supertraits.allTraits, + trait, + ]) as SpreadSupertraits + } + + build() { + return this.expression as BuildTraitExpression + } + + then(fn: (expression: ReturnType) => V): V { + return fn(this.build()) + } +} + +export const expression = new TraitExpressionBuilder(emptyTraitExpression) diff --git a/src/abstract.ts b/src/abstract.ts new file mode 100644 index 0000000..c6502e4 --- /dev/null +++ b/src/abstract.ts @@ -0,0 +1,10 @@ +import { Opaque } from "type-fest" + + +export type AbstractTag = "@thilawyn/traitify-ts/Abstract" + +export function abstract< + Abstract extends {} = {} +>() { + return {} as Opaque +} diff --git a/src/expresses.ts b/src/expresses.ts deleted file mode 100644 index 5784e56..0000000 --- a/src/expresses.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { AbstractClass, Opaque } from "type-fest" -import { Trait, TraitApplierSuperTag } from "." -import { ClassesInstances, ClassesStaticMembers, MergeInheritanceTree, MergeInheritanceTreeWithoutOverriding, StaticMembers, TraitsClasses } from "./util" - - -/** - * Extends a class with the given traits and expresses their combined functionality. - * @template C - The abstract class type. - * @template Traits - An array of traits. - * @param extend - The class to extend. - * @param traits - An array of traits to apply. - * @returns A new class type expressing the combined functionality of the base class and traits. - * @example - * Extends a superclass and applies traits: - * ```ts - * class User extends extendsAndExpresses(Entity, - * Identifiable(), - * Permissible, - * ) { - * readonly id: bigint - * - * constructor(id: bigint) { - * super() - * this.id = id - * } - * } - * ``` - */ -export function extendsAndExpresses< - C extends AbstractClass, - Traits extends readonly Trait[], ->( - extend: C, - ...traits: Traits -) { - return traits.reduce( - (previous, trait) => trait(previous), - extend as Opaque, - ) as unknown as ( - AbstractClass< - MergeInheritanceTreeWithoutOverriding<[ - InstanceType, - ...ClassesInstances< - TraitsClasses - >, - ]>, - - ConstructorParameters - > & - - MergeInheritanceTree<[ - StaticMembers, - ...ClassesStaticMembers< - TraitsClasses - >, - ]> - ) -} - -/** - * Expresses the combined functionality of multiple traits. - * @template Traits - An array of trait. - * @param traits - An array of trait to apply. - * @returns A new class type expressing the combined functionality of the traits. - * @example - * Applies traits to a class: - * ```ts - * class User extends expresses(Identifiable(), Permissible) { - * readonly id: bigint - * - * constructor(id: bigint) { - * super() - * this.id = id - * } - * } - * ``` - */ -export function expresses< - Traits extends readonly Trait[], ->( - ...traits: Traits -) { - return extendsAndExpresses(Object, ...traits) -} diff --git a/src/index.ts b/src/index.ts index ae86066..bf1c52b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,4 @@ -export * from "./expresses" -export * from "./trait" +export * from "./Trait" +export * from "./TraitExpression" +export * from "./TraitExpressionBuilder" +export * from "./abstract" diff --git a/src/lib.ts b/src/lib.ts new file mode 100644 index 0000000..0f31a88 --- /dev/null +++ b/src/lib.ts @@ -0,0 +1,6 @@ +export { + abstract, expression, trait, + type Implements, + type Trait, + type TraitExpression +} from "." diff --git a/src/tests.ts b/src/tests.ts index cff84f8..f8bede5 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,131 +1,81 @@ -import { AbstractClass } from "type-fest" -import { expresses, extendsAndExpresses, trait } from "." -import { ClassesInstances, MergeInheritanceTree } from "./util" +import { Simplify } from "type-fest" +import { Implements, Trait, abstract, expression, trait } from "." +import { Pipe } from "hotscript" -const Identifiable = () => - trait(Super => { - abstract class Identifiable extends Super { - abstract readonly id: ID - - equals(el: Identifiable) { - return this.id === el.id - } - - constructor(...args: any[]) { - super(...args) - console.log("Identified constructor") - } - } - - return Identifiable - }) - -const ImplementsIdentifiable = (defaultID: ID) => - trait(Super => { - abstract class ImplementsIdentifiable extends extendsAndExpresses( - Super, - Identifiable(), - ) { - id: ID = defaultID - - constructor(...args: any[]) { - super(...args) - console.log("ImplementsIdentifiable constructor") - } - } - - return ImplementsIdentifiable - }) - - -const Permissible = trait(Super => { - abstract class Permissible extends Super { - static readonly defaultPermissions: string[] = [] - permissions: string[] = [] - +const PrintsHelloOnNew = trait( + abstract(), + Super => class PrintsHelloOnNew extends Super { constructor(...args: any[]) { super(...args) - console.log("Permissible constructor") + console.log("Hello!") } - } - - return Permissible -}) - - -const UserProto = expresses( - // Identifiable(), - ImplementsIdentifiable(0n), - Permissible, + }, ) -class User extends UserProto { - constructor(id: bigint) { - super() - this.id = id - } -} +const Identifiable = () => trait( + abstract<{ readonly id: ID }>(), + Super => class Identifiable extends Super { + equals(el: Identifiable) { + return this.id === el.id + } + }, +) -const user1 = new User(1n) -console.log(user1) -console.log(user1.equals(user1)) - - -const Test1 = trait(Super => { - abstract class Test1 extends Super { - declare static name: string - declare static testValue: ( - { _tag: "type1", value: string } | - { _tag: "type2", value: number } - ) - - abstract name: string - - declare createdAt: Date - declare readonly status: ( +const StatefulSubscription = trait( + abstract<{ + readonly isStatefulSubscription: true + readonly status: ( { _tag: "awaitingPayment" } | { _tag: "active", activeSince: Date, expiresAt?: Date } | { _tag: "expired", expiredSince: Date } ) - } + }>(), - return Test1 -}) + Super => class StatefulSubscription extends Super {}, +) -const Test2 = trait(Super => { - abstract class Test2 extends Super { - declare readonly status: { _tag: "active", activeSince: Date, expiresAt?: Date } - } +const ActiveStatefulSubscription = expression + .expresses(StatefulSubscription) + .build() + .subtrait( + exp => { + interface IActiveStatefulSubscription extends Implements { + readonly isActiveStatefulSubscription: true + readonly status: { _tag: "active", activeSince: Date, expiresAt?: Date } + } - return Test2 -}) + return abstract() + }, -const Test3 = trait(Super => { - abstract class Test3 extends Super { - declare static testValue: { _tag: "type2", value: number } - declare lol: 10n - } + Super => class ActiveStatefulSubscription extends Super {}, + ) - return Test3 -}) - -const TestObjectProto = expresses(Test1, Test2, Test3) -TestObjectProto.testValue +type T = Trait.Instance -interface Gneugneu { - ahi: string - get adolf(): string +class TestSuperclass { + // id: number = 69 + // static test = 69 } -class GneugneuImpl implements Gneugneu { - ahi: string = "" - get adolf(): string { - throw new Error("Method not implemented.") - } +const exp = expression + .extends(TestSuperclass) + .expresses( + PrintsHelloOnNew, + Identifiable(), + // Identifiable(), + ActiveStatefulSubscription, + ) + .build() +type Abs = Implements + +class User extends exp.extends implements Implements { + readonly isStatefulSubscription: true = true + readonly isActiveStatefulSubscription: true = true + declare status: { _tag: "active"; activeSince: Date; expiresAt?: Date | undefined } + id: bigint = -1n } -abstract class Issou extends GneugneuImpl implements Gneugneu { -} +console.log(new User()) diff --git a/src/trait.ts b/src/trait.ts deleted file mode 100644 index 21fd00c..0000000 --- a/src/trait.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { AbstractClass, AbstractConstructor, Opaque } from "type-fest" - - -/** - * Represents a trait that can be applied to a class. - * @template C - The abstract class type. - */ -export type Trait< - C extends AbstractClass -> = Opaque< - TraitApplier, - "@thilawyn/thilatrait/Trait" -> - -export type TraitApplierSuperTag = "@thilawyn/thilatrait/Super" - -/** - * Represents the function signature for applying a trait to a parent class. - * @template C - The abstract class type. - */ -export type TraitApplier< - C extends AbstractClass -> = ( - (Super: Opaque, TraitApplierSuperTag>) => Opaque -) - -/** - * Creates a trait using the provided trait applier function. - * @template C - The abstract class type. - * @param applier - The trait applier function. - * @returns A trait. - * @example - * Creates a trait: - * ```ts - * const Permissible = trait(Super => { - * abstract class Permissible extends Super { - * static readonly defaultPermissions: string[] = [] - * permissions: string[] = [] - * - * // Constructor is optional - * // If you wish to use it, make sure it takes any[] as an args array and passes it to the super call. This is necessary for inheritance to work properly. - * // Trait constructors cannot have typed arguments of their own, they only serve to run logic during object instantiation. - * constructor(...args: any[]) { - * super(...args) - * } - * } - * - * return Permissible - * }) - * ``` - * Creates a generic trait: - * ```ts - * const Identifiable = () => - * trait(Super => { - * abstract class Identifiable extends Super { - * abstract readonly id: ID - * - * equals(el: Identifiable) { - * return this.id === el.id - * } - * - * // Optional - * constructor(...args: any[]) { - * super(...args) - * } - * } - * - * return Identifiable - * }) - * ``` - * Creates a subtrait: - * ```ts - * const ImplementsIdentifiable = (defaultID: ID) => - * trait(Super => { - * abstract class ImplementsIdentifiable extends extendsAndExpresses( - * Super, - * Identifiable(), - * ) { - * id: ID = defaultID - * - * // Optional - * constructor(...args: any[]) { - * super(...args) - * } - * } - * - * return ImplementsIdentifiable - * }) - * ``` - */ -export function trait< - C extends AbstractClass ->( - applier: TraitApplier -) { - return applier as Trait -} - -/** - * Returns the class type of a trait. - * @template T - The trait type. - */ -export type TraitClass = ( - T extends Trait - ? C - : never -) - -/** - * Returns the instance type of a trait. - * @template T - The trait type. - */ -export type TraitInstance = ( - T extends Trait - ? InstanceType - : never -) diff --git a/src/util/class.ts b/src/util/class.ts deleted file mode 100644 index 325aba5..0000000 --- a/src/util/class.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { AbstractClass } from "type-fest" - - -/** - * Represents an array of instances corresponding to the provided classes. - * @template Classes - An array of classes extending AbstractClass. - */ -export type ClassesInstances[]> = ( - Classes extends [infer Class, ...infer Rest] - ? Class extends AbstractClass - ? Rest extends AbstractClass[] - ? [InstanceType, ...ClassesInstances] - : never - : never - : [] -) - -/** - * Represents an intersection of instances of the provided classes. - * @template Classes - An array of classes extending AbstractClass. - */ -export type ClassesInstancesIntersection[]> = ( - Classes extends [infer Class, ...infer Rest] - ? Class extends AbstractClass - ? Rest extends AbstractClass[] - ? InstanceType & ClassesInstancesIntersection - : never - : never - : {} -) - -/** - * Represents the static members of a class. - * @template Class - A class extending AbstractClass. - */ -export type StaticMembers> = ( - Omit -) - -/** - * Represents an array of static members corresponding to the provided classes. - * @template Classes - An array of classes extending AbstractClass. - */ -export type ClassesStaticMembers[]> = ( - Classes extends [infer Class, ...infer Rest] - ? Class extends AbstractClass - ? Rest extends AbstractClass[] - ? [StaticMembers, ...ClassesStaticMembers] - : never - : never - : [] -) - -/** - * Represents an intersection of static members of the provided classes. - * @template Classes - An array of classes extending AbstractClass. - */ -export type ClassesStaticMembersIntersection[]> = ( - Classes extends [infer Class, ...infer Rest] - ? Class extends AbstractClass - ? Rest extends AbstractClass[] - ? StaticMembers & ClassesStaticMembersIntersection - : never - : never - : {} -) diff --git a/src/util/extend.ts b/src/util/extend.ts new file mode 100644 index 0000000..d675de5 --- /dev/null +++ b/src/util/extend.ts @@ -0,0 +1,25 @@ +import { Call, ComposeLeft, Fn, Match, Tuples } from "hotscript" +import { CommonKeys } from "." + + +type ExtendReducer = ( + Pick> extends Pick> + ? Omit> & Self + : never +) +interface ExtendReducerFn extends Fn { + return: ExtendReducer +} + +export type ExtendFn = Tuples.Reduce +export type Extend = Call + + +export type ExtendableFn = ComposeLeft<[ + ExtendFn, + Match<[ + Match.With, + Match.With, + ]> +]> +export type Extendable = Call diff --git a/src/util/index.ts b/src/util/index.ts index c5faea6..720a972 100644 --- a/src/util/index.ts +++ b/src/util/index.ts @@ -1,3 +1,3 @@ -export * from "./class" +export * from "./extend" export * from "./inheritance" -export * from "./trait" +export * from "./misc" diff --git a/src/util/inheritance.ts b/src/util/inheritance.ts index a179d78..8d9a516 100644 --- a/src/util/inheritance.ts +++ b/src/util/inheritance.ts @@ -1,9 +1,5 @@ -/** - * Represents the common keys between two types. - * @template A - The first type. - * @template B - The second type. - */ -export type CommonKeys = Extract +import { CommonKeys } from "." + /** * Merges an inheritance tree defined by an array of types, considering overrides. diff --git a/src/util/lib.ts b/src/util/lib.ts new file mode 100644 index 0000000..4e2038a --- /dev/null +++ b/src/util/lib.ts @@ -0,0 +1,6 @@ +export { + Extend, + ExtendFn, + Extendable, + ExtendableFn +} from "." diff --git a/src/util/misc.ts b/src/util/misc.ts new file mode 100644 index 0000000..3e19396 --- /dev/null +++ b/src/util/misc.ts @@ -0,0 +1,25 @@ +import { Fn } from "hotscript" +import { AbstractClass, Simplify } from "type-fest" + + +/** + * Represents the common keys between two types. + * @template A - The first type. + * @template B - The second type. + */ +export type CommonKeys = Extract + +export interface SimplifyFn extends Fn { + return: Simplify +} + +/** + * Represents the static members of a class. + * @template Class - A class extending AbstractClass. + */ +export type StaticMembers> = ( + Omit +) +export interface StaticMembersFn extends Fn { + return: StaticMembers +} diff --git a/src/util/trait.ts b/src/util/trait.ts deleted file mode 100644 index 149599d..0000000 --- a/src/util/trait.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Trait, TraitClass } from ".." - - -/** - * Represents an array of classes corresponding to the provided traits. - * @template Traits - An array of traits extending Trait. - */ -export type TraitsClasses[]> = ( - Traits extends [infer T, ...infer Rest] - ? T extends Trait - ? Rest extends Trait[] - ? [TraitClass, ...TraitsClasses] - : never - : never - : [] -)