From 7791baff20ececf220c62fdeb864e6211951b2d4 Mon Sep 17 00:00:00 2001 From: garrettmills <shout@garrettmills.dev> Date: Tue, 24 Dec 2024 09:43:23 -0500 Subject: [PATCH] Big bang --- .gitattributes | 1 + .gitignore | 175 +++++++++++++++++++++++++++++++++++++++++++++ README.md | 15 ++++ bun.lockb | Bin 0 -> 13883 bytes index.ts | 4 ++ package.json | 16 +++++ src/bones/index.ts | 1 + src/bones/types.ts | 89 +++++++++++++++++++++++ src/config.ts | 20 ++++++ src/types.ts | 23 ++++++ tsconfig.json | 27 +++++++ 11 files changed, 371 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 README.md create mode 100755 bun.lockb create mode 100644 index.ts create mode 100644 package.json create mode 100644 src/bones/index.ts create mode 100644 src/bones/types.ts create mode 100644 src/config.ts create mode 100644 src/types.ts create mode 100644 tsconfig.json diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..81c05ed --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.lockb binary diff=lockb diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9b1ee42 --- /dev/null +++ b/.gitignore @@ -0,0 +1,175 @@ +# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore + +# Logs + +logs +_.log +npm-debug.log_ +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Caches + +.cache + +# Diagnostic reports (https://nodejs.org/api/report.html) + +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# Runtime data + +pids +_.pid +_.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover + +lib-cov + +# Coverage directory used by tools like istanbul + +coverage +*.lcov + +# nyc test coverage + +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) + +.grunt + +# Bower dependency directory (https://bower.io/) + +bower_components + +# node-waf configuration + +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) + +build/Release + +# Dependency directories + +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) + +web_modules/ + +# TypeScript cache + +*.tsbuildinfo + +# Optional npm cache directory + +.npm + +# Optional eslint cache + +.eslintcache + +# Optional stylelint cache + +.stylelintcache + +# Microbundle cache + +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history + +.node_repl_history + +# Output of 'npm pack' + +*.tgz + +# Yarn Integrity file + +.yarn-integrity + +# dotenv environment variable files + +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) + +.parcel-cache + +# Next.js build output + +.next +out + +# Nuxt.js build / generate output + +.nuxt +dist + +# Gatsby files + +# Comment in the public line in if your project uses Gatsby and not Next.js + +# https://nextjs.org/blog/next-9-1#public-directory-support + +# public + +# vuepress build output + +.vuepress/dist + +# vuepress v2.x temp and cache directory + +.temp + +# Docusaurus cache and generated files + +.docusaurus + +# Serverless directories + +.serverless/ + +# FuseBox cache + +.fusebox/ + +# DynamoDB Local files + +.dynamodb/ + +# TernJS port file + +.tern-port + +# Stores VSCode versions used for testing VSCode extensions + +.vscode-test + +# yarn v2 + +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +# IntelliJ based IDEs +.idea + +# Finder (MacOS) folder config +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..5d3181b --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# email-comments + +To install dependencies: + +```bash +bun install +``` + +To run: + +```bash +bun run index.ts +``` + +This project was created using `bun init` in bun v1.1.42. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime. diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..93f63c1cba7ec9eadf5c0450dbb29bef43a885ef GIT binary patch literal 13883 zcmeHOdt6N0+n+LtBBeqUC809Y{eGczj=M@x2u;(J=`vF@(?xC*x!=M;BKJ!aLb*js z$u$bOlu(Xq#Bo2O^FGg>S=r}sD&F58zxVxke0I;Qz1R2qJnPwOueJ8t4?_d97_rDK zh%YeX31anwVgxF1up)%q@DP3kj};;mMRFvpSaTIc27@uybYh?K`)4Lj$atwVb#3(c z!39b0+6)^r>CdXUq5WOTt21n%5=bwZVzl{(mdeXoqykk|V=$x%!eHt*Kavv_5+RHe zg9BnX(_VqWXb0C@fmQ*%O0L7iK>`Fs@dZNE*TB8ba9tb~!IxMv7<o|c1m#_zwGjte z3v?1_4bU;5JAj@Hx;^Ls&}hd?u73fo3S}qIX!i`*K%ED=E$9e-P;?ah1|7+d<S}yO z=QHH>)+@{SQlX6YdV)rKA_xic9tMr}y2$H00x9y&kZXtuWzWQ<yQ@^^WILAa{n|ku zGYjl?sd<km%sq8PT+*p)oX=C&dm~MU9s4*>U9E2O{xl8mm1A})4BoDA++m8&;d__T ziq~pecJ>)GX!ZWB20n+ab#52gvK8Mh+L@WOvATDMlL`JGpEU^HWfYvVs`CwL?Ge8A zRI6v(w7b?Hx^ZJ$p<kw&j;l$H=CkyV-8B<JP8(bHnSRT8^s4ZiQ%f!{+xg~NY2GuI zpI`g&s~k@*I&)`aeC9o~s`$yh3j9}{4z?@mGQs+YiS7o)lRbu5TP{+25_&*n_xRjC z*JHuH&ia40@0p`LVAD&pg2hAGwP#Mc$Bb>;Zis5ha<g$udgr(}v=urRKlM({J>S~+ z#4z*3H&dU5mdx*1+jHxMlqnm-uJAV+N&A`3;RQi=_+JU!UP>(BuNlO@6==LCE#)Qn zK)^Txp5U+_v_uHL3@Ssnm0}s68uX(jLhw3ZcmUv;03zqU2R|0@&VYyRM~PBPz)*+S z+9=0k`|<c*|0@Ax4)zJYh2|UWtAZnlNB>*uJK7-r*TRo6fG6eeweJQEwg&u<#y<w| zzH&U;MxK@k@%J3yM*$woKhpkgV9*QjFl>F75c}bPA1b$x_mG@#j*QgH0sOCkZ)v*; zFTvLX&>isD@6dirh2UKvXafL`IC2huHz%a-bUFTeY$G?pp8&k8-2WfBfAs*u=NIEg zIGgjGZr`pogW&>rP&f}U)LR0EI>eR)fH?l4@89DC!S4k;8UMa#3?TS>fVY*~$3B4V zXo(PfC+PTO{6>6Bh2XsakMTzw+HNTa!KVX$0N}CwBhSxcz?0{XZ~|4cLh4$=q%#2Q zlm4sOEK*j1;HLu~;|FUjT-Pvg{n8R4_(H(D0UrBLS2$Yw3=ljMIxXIR(s#bs{y@Mx z(eOqsaUSXr`||*g<3G;b=sT<_TO<U32JqN_5DT}mk+&rzh`|E|HBeFUM{e>QqsDSa zI8f*s)}stPI52kI;XwHwjkq2Z>f0Kx>&vgB#%IG&UPg`MMIU(?HP-JdFVi)iH<n*F zkzYrR=S|_j_Oaw;HfSP0<I_}p8agy!0RNK$d<qO1FP)m1T3s*g_&IAysK`*qZ|{u< zZ_fAa`25uBDZX7}@(PnLxeTA1HTHhn(JGPmrd(O;e@x=kXZx#Dt*1Xe_$X=bhX+0% zXuRaPLAROrroZpx{(E^=LCl*uS01j{@~)e+&u*Ca)D89#EA+CDKX)&9IAd|$(V3Fj z_YVbZ@*Je0Hfq<yq<rI^173Qruxm4q#!DZ!nQPWh9sNrufz2<GJB!UUuP<Mu+*89W zWs*bAf$rL?*8j2c`KF5p1l0y+2Sigp_ElY0b-y6c(R#r|Ri#ggo`FWkLutI&$B8iC z&mUSEKP~fP@|p-garCpvUDX1%$Ceg7b{*9DWb3m-f{G5-9m(o?G}*sTh5JCg6Q29b zM46xUinHdw)e2aY?Po&cCC@!_GcQi{x)^52lf2|vl<q#1r(u~^ZTvp3P3{q$?XGjm z$EK#_)$GV#V)S{8&(h61jFv^eE|}}EWBLc7$FQ^R)vldi(Rk_eC)06Rwujs3M|W#4 z$M@)UC3(J1)U?<Y8pbi(3l1=}`fU*P@UM=1ypsEnkv^N}Xnttsr^J*FPx4=hT-RD} z_VAcEnZ}D_8xdypA#J}{sb%Tak#(-c`8UHeEZ;;dsJ&Z}df~+W#Mn#eH67;;c+@fI zcGtU;rl!=t>YltP*GhS0<n_XFsXCHw??2Iaaoi=sJZ;ds!@^-{6XOpL9O+e+aMpOL zhcrgKO3U%gQN4ai6HECY{FMe8-chR!__O_5r<3n0UiJ3NnbgtZuNyY8?oan|X}ma= z5@B}U^T)%R2mQ9snwON|F>TAub2F??w6f8D{#SLr?c#Pb#szlqVVoD1n+WDUUzz-? z<C5pG#YKCD&8|!c$rU@K@3W%ust{7pOz*R|dp+2;;b3s*trsShJdF}N_Knx>drP}E z#5sIjO8fDj&y^+nF_g`B&y%FwDfhj;!@syJ#JG)pc-vC7z!{q3XuLR<6Jh2^a|Zec zp6fPm);R6YbDmYUpK?rGKJWa-+>f(HeDLAyN-aG6YVMPT;SqDUUrT?Td-HDCS&@H3 z_1hG;n05!tl=Eo3IHwa~3KO1ex7_iz|FZpFiRuqD?r&agc(}^3#M*a9O#KZTjlha_ z7w)@V+T)`-=j_68>1565Fm1h_89oK?%a`Zhdaj{M<E77&%&Aq5+MTRFmdDna99dd( zaLDY+Q7&m)dGCy7FiZM$y|L%5x?Zx8l8H`Mokpka&$9M7uIJV2HEj6kV*M^4)uE>r zjh8<EGs|j*aMS(zg}yyn_Hx>d=dCw4%sx@%Bb{<}!L9h+;_Jm4#yj(8=~}3-+o{aW z&9n_Rn_WDkP&>`$*3H2+k;m3&(Rg7Gr%{-nE~a$o7I``AZkIykMW&1_Z~OE~yWFIV z*Y->Q5(oS;uJpm1Z6D4(t8P7@A<46|)9v&MZ6is0|I&VO3_sQobyFHInWvGQ>6p1J zwDQE0aR#jnd-O53N;SQ-XGzwyqK&uNKG~y2OYhEGw`1$ak4ke#<t<;{<|M~$-sq1L z(+XEdEuH3JryMlxF^w1Yo*ISu=x}W&x4(U_3+V@?^M-8p?J$~IP*q><#5=K4w;)Yv zsE%*#uMz9-7Z<l~mzMvgb(b~`1{*VTMvSR&_;me{;MYzxUb22ba%S??t!kSL>efpp za0k~Xb-Ofwd4uG4U8N;QtM=xJ!j8DiJhM7iqxEnj7lznzVOiUcb#wcVu(o04sD#<_ zcZytcXuR}wCo@j9ue)#Vyqm+P%rPk!=2eOZMs+N|w|l9rNVEN<flJ;T&hXvTju);} z`C@oZ-<)vI!LAki1IypP+_8V<tCw;0r8Hh#ml9#>U#}ltQr{4$o5f%MPWOP}zT`m( zWjAcRb7v%$-k2M(>yrJEwGMx1JkWQw%c);E?Kh6@g|R!Uj+(#drCfNh9kY<e3ww)= z!rYP1=3P7MQRS?=eZnVCwaD@W>$;NRo$O5V50_57cyId14MC^8uCI8sna|Z-SDAU8 z)i0&<)q|oQLj&UnC8+jvpz*@qWuq{w&scT)d^R^hwB}Ucz`Qh*!I{Sn`K;44Z8eYk z`GsDEWlEIqt!EcUUTPmW(nPaeVV(9g%{}9nG_>QaIGCG%#3`M|3wxxE!Ym7&(dE-y zrwJdT8V+$r%pHEeq*b>58c)A`lf{o5-A-OA@-V8J<|HznTK@d9Z)L>l-reopQWG~9 zga%Z_nBLjFmBx#EW<;3FZY8Q7-m;s$QL35W_0_C^6$=JSJBGz7-5VsW(H9SnR6gA< zWTGU_`1tBw4j)uiRfar#s`7c`gV;%ox=d4hvwRw_4j~22?AmHgoLk?gDgLwcTJ^qJ zT5<JwOi3Hx*^$9(q#p0L=%;R)T3xk2c<*HEJFlI*>iXZdFBP><dmXR$?stWnlPj}h zX}tK3L4;ZTa@&jB{gTdzEz>f3jNCo$fJcpqQTh>gubE31*691ZSg!1O;@+)+W+mgY z>xw6B5O`&5*g7m)w^FFt)3HNN8hu>vMo2+3IjMH0B`Z2)2c2gzuX%LXV)?pm=)@h8 zWWy_#F8j~S9(`j%ZRLY2gX=0pc7d&mLe(Rpb5C4c-hG6wP-VUQk>3u{{MDuNcB~n5 z%KLKYs7i*@!r{ik?zg*59{VBlUPFv}xACSX>JQ4qJoci&Lwbsb>^(E6?DEp2Wcv+S zi802V?wS9|Rqsn5A8_4Igz2+Pn-_Ov!u(OU6-F4=^*yF^+(BeNddt?c6Z+`HYhRo_ zZE(HIYQ06y*M^r)nQ!&j*HbNf%|YeFY_(V2di<%T^@!##d4E7|=KgbqkFN0p`^OZ= zo4P3$Cwm?nwf|awyM?^ToW)wHw<X(7*_MiDx@Jfw8+e<aR#;vrc3qajw{GRSS}87i zoM|eJm%L|CyuG~^J3ZPgaaY;x9ldf(k1<lMF_W#HpLV*~zxr*gB*QL!zrjPVRU=D! znVm>V89PNOz-<1s11k*PSDzfF9r83`8;w^V3FX4vvdVwH_a3K^jb*p4D_tM6+C;VW z;!zT-qq`S$4Y#b$I9-|@GM>B8|L&`3Zt;YfA3XBI*9kTh?OFBMZqnw;KAA-{UIRi3 znyI>%cXDUqKG9_(&e#f7^Yi=HzUFh+&+M_v+xl+jHAU$`x0dheWO!s@(a_<$YI3r7 z=cwz3?dUjYC--oGf#F_h1dX>Rop(!N|HMEa=X7Pi)4z{=@+g5>*7L&Yr;B^fT<_Yu zw1<<L)2)ig*hszK!ao$5CUj$JM6uTR*1quYd=sIf9(5u)nZ`@r%aESAXkEe+jX%`h zj=1l3w|$jomPd7$TMx_)HSbty9h*P>FOP~{q5EtXJm+87Io?omGt1@kt8N<n0KGN( z!*_gkpSx%V@cy?8zDJO6NbnJi9flvBe#*}XKm^D;8__=!l>Y;dz>hTRC+24aen#MD z1b#-~|6v6Dd&wFVA=fI-ViA|k7l<XChzK@G4PyI>csy5qOLKiOKY=F<>8Ee4&xzoN z3WOo@&8>#NWP)tCu1t~h^)iz2t2oD4S-Jx3UkGsS#Pu2O$>JQ0d;R!50QWp`e-if+ zao-R3=+GqYec?V8?kVB-0Q^>f-xKiNANLjT9TnfB@SPIhgYjJr-{0|F5cf0iog4R! zaE}Myi*Qc{_fNd!{<i521(2rv#&+t%fq3*C+kiIF2HHg*&^Fpa+vq>G58H%o#5Q5u zh|lO3`hdQmU+5pU58H|DC2hw#SeI^tZkMzd-^=hF$^Z_0hrlu(_VTv<jzI=daUO4J zJ0Zp%Zm@0R{jvCRgV7I&xs>GLs4GmgVVkqfWi7-jBy*>Y!bA%;{IjO)K^vqb*GCbr zn6oV$7$ob9WH*s3b`~TrjO0JT6)U!-HQR!b3LZeKr6hw$QNfaJi4HI_<i3$yBSi&s zwk_KV&XO!Gl8vOOV8OPcFeHzQ<SQvE*uWL|qKFw@RHhfnXhJ*C9JrDP2gF}Wa-I-l z&9;QIXW+mXkgO<01zWZQ+XCpwy9UY2QdDqYL*Sr3$#^4~U1-Oi@|xtnksL3Gfdj<N z26_T?FX#zUk_84=zyYKq`Eeu<3|k7p20J8!j%12av4$|f_fP1s=rzgdqS)a6Fc>5o zj%0no6)RZ~NWL7&3!~Vmen2wnNah$^F_-y9a_&fO8O26nNLC)nK7%XPvR*~<_DFsj zT*2D_4I-I+B!dmE*vT*?_mAYbQ5f+1OLid1f|J{U7?3<dk}pSLDBnnCA<3YVW59!d zZ|T2B=ReyM|KrcXzw~&L)kw1U6crZ3fTa$7hU7Jp{5?el6X<IwB-4>(^eHOLuwh%; zvaJ~;=aJ<0$@-|39fLu#AW60#VC>;Bu`p+RZD)ohbWwOzzP>^{FvrONBucLTKA(ws zk+D1x`<HkLPbA<(_((*2L8z;~#g}2v{>!k(kchbySAM<LcF}LiT9`PC=Q`Zk>RhK6 zeM}-2^F+Wm;i`V(sE}bFa$$hLCp5|4=AuHpTEix}4_o2sMS-~l##oDQ4YAa9UL=Pf z!Qu)dBY6UeSTZGwC+3RyQIY}FPcz8XmH#3`=wyimz8{&HiFl!Wu|zb5Er^N?6SIY) zP%{`y%~<%CB^yH7lF)=EsuM=Qke@7SytcDIBu~H<21BS=VVo$AfG6hhxk5oK3({|S zFk}XC#5`MTbe?){1j1mdB|K3R2B{GctWlapjecl|AI0JX2a9-Ou{e?=lCXkeLPDD6 zp;bdVT9HK!kIgl_(I7UxvB07RUBrr`ppQsGSYhI(TGLnweP}E|2yxD7I`lYt0}2&Y z-@KXnIIBQ?RNy5}#OS3^z~{1pgu=)Wj#$DH@q#&A2}dG~gtOuZ9xqD7<3zye=or3; zCz%YTU>5Wk9w#zNB;-Q4S#cbZ0Pe6*z~aU8C9DV@C!7@mt3Jw(SOV2~B0jA75_lr9 zm=nSSI41~_#(@Q3{E#U?%>{@ohdc&436~Sa3#Q<lAgBcnvEZ*j93>P<nuz7UAV`zH z=7Qb>gLX4fla1)q-NB^s7WIv9w+J}CeE~SlVNKBV-Tr3i(5-KU6j~;~zs<$#A2)~u z>mR3C)MVL=hhOyoAp7bZcxC|;eA8|HN7q89{@&TBh&6ZT{?=Q8<8Ngc-Ef#{+7Ei) z2LgJLMJ-dB!PB23z|)J=AlaOK+9L^YS_!;w{{DV>v;q93(4rpvWhe&hmjX++LT#qm zjRQJh8-KH?Wp6V`Y8eeEN>g2hnnjxE#84CeYlRGhzrYSG$(y$$n|ow9*>AWdu*`1; z`DOkB=$8U?2Y7ivtgDMY)y4Il^^wgSpHEQ>rXyN4V5Xy5^vHZQ(E`a==YR=^yrw(- zKb8vEO!<Geq57<a1LEbCuxB)Jb7-}I1}n2<>o5yyw2Ki0^SOK$wMc1#g<cJ4=ta2M zut>CNS&Lv91aSP1OE|mAT)<Lu_8aTS(Nukk!^(~pi@2udd3hw_#J~|JW>M=@s=LUR fhO*^g6EUD{QfoRO_)>uO+sQ^#Y907r_~(BBO~~@X literal 0 HcmV?d00001 diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..9716130 --- /dev/null +++ b/index.ts @@ -0,0 +1,4 @@ + +import { config } from "./src/config.ts"; + +console.log(config) diff --git a/package.json b/package.json new file mode 100644 index 0000000..218b3df --- /dev/null +++ b/package.json @@ -0,0 +1,16 @@ +{ + "name": "email-comments", + "module": "index.ts", + "type": "module", + "devDependencies": { + "@types/bun": "^1.1.14" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "dependencies": { + "@types/imapflow": "^1.0.19", + "imapflow": "^1.0.171", + "zod": "^3.24.1" + } +} \ No newline at end of file diff --git a/src/bones/index.ts b/src/bones/index.ts new file mode 100644 index 0000000..c9f6f04 --- /dev/null +++ b/src/bones/index.ts @@ -0,0 +1 @@ +export * from './types' diff --git a/src/bones/types.ts b/src/bones/types.ts new file mode 100644 index 0000000..f8399c4 --- /dev/null +++ b/src/bones/types.ts @@ -0,0 +1,89 @@ +/** Type alias for something that may or may not be wrapped in a promise. */ +export type Awaitable<T> = T | Promise<T> + +/** Type alias for something that may be undefined. */ +export type Maybe<T> = T | undefined + +export type MaybeArr<T extends [...any[]]> = { + [Index in keyof T]: Maybe<T[Index]> +} & {length: T['length']} + +export type Either<T1, T2> = Left<T1> | Right<T2> + +export type Left<T> = [T, undefined] + +export type Right<T> = [undefined, T] + +export function isLeft<T1, T2>(what: Either<T1, T2>): what is Left<T1> { + return typeof what[1] === 'undefined' +} + +export function isRight<T1, T2>(what: Either<T1, T2>): what is Right<T2> { + return typeof what[0] === 'undefined' +} + +export function left<T>(what: T): Left<T> { + return [what, undefined] +} + +export function right<T>(what: T): Right<T> { + return [undefined, what] +} + +export function unleft<T>(what: Left<T>): T { + return what[0] +} + +export function unright<T>(what: Right<T>): T { + return what[1] +} + +/** Type alias for a callback that accepts a typed argument. */ +export type ParameterizedCallback<T> = ((arg: T) => any) + +/** A key-value form of a given type. */ +export type KeyValue<T> = {key: string, value: T} + +/** Simple helper method to verify that a key is a keyof some object. */ +export function isKeyof<T extends object>(key: unknown, obj: T): key is keyof T { + if ( typeof key !== 'string' && typeof key !== 'symbol' ) { + return false + } + + return key in obj +} + +/** A typescript-compatible version of Object.hasOwnProperty. */ +export function hasOwnProperty<X extends {}, Y extends PropertyKey>(obj: X, prop: Y): obj is X & Record<Y, unknown> { // eslint-disable-line @typescript-eslint/ban-types + return Object.hasOwnProperty.call(obj, prop) +} + +/** + * TypeScript helper for creating tagged-types. + */ +export interface TypeTag<S extends string> { + readonly __typeTag: S +} + +export type PrefixTypeArray<T, TArr extends unknown[]> = [T, ...TArr] +export type SuffixTypeArray<TArr extends unknown[], T> = [...TArr, T] +export type TypeArraySignature<TArr extends unknown[], TReturn> = (...params: TArr) => TReturn + +export type MethodsOf<T, TMethod = (...args: any[]) => any> = { + [K in keyof T]: T[K] extends TMethod ? K : never +}[keyof T] + +export type MethodType<TClass, TKey extends keyof TClass, TMethod = (...args: any[]) => any> = { + [K in keyof TClass]: TClass[K] extends TMethod ? TClass[K] : never +}[TKey] + +export type Awaited<T> = T extends PromiseLike<infer U> ? U : T + +export type Integer = TypeTag<'@extollo/lib.Integer'> & number + +export function isInteger(num: number): num is Integer { + return !isNaN(num) && parseInt(String(num), 10) === num +} + +export type ArrayElement<ArrayType extends readonly unknown[]> = + ArrayType extends readonly (infer ElementType)[] ? ElementType : never; diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..54afd59 --- /dev/null +++ b/src/config.ts @@ -0,0 +1,20 @@ +import {castCommentsConfig, type CommentsConfig} from "./types.ts"; + +const maybeConfig: any = { + mail: { + imap: { + host: process.env.CHORUS_IMAP_HOST, + port: process.env.CHORUS_IMAP_PORT || 993, + auth: { + user: process.env.CHORUS_IMAP_USER, + pass: process.env.CHORUS_IMAP_PASS, + }, + }, + threads: { + type: 'alias', + template: process.env.CHORUS_THREAD_TEMPLATE, + }, + }, +} + +export const config: CommentsConfig = castCommentsConfig(maybeConfig) diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..426d2f3 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,23 @@ +import {z} from "zod"; + +const commentsConfigSchema = z.object({ + mail: z.object({ + imap: z.object({ + host: z.string(), + port: z.number({ coerce: true }), + auth: z.object({ + user: z.string(), + pass: z.string(), + }), + }), + threads: z.object({ + type: z.string(), // fixme : in validation + template: z.string(), + }), + }), +}) + +export type CommentsConfig = z.infer<typeof commentsConfigSchema> +export const castCommentsConfig = (what: unknown): CommentsConfig => { + return commentsConfigSchema.parse(what) +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..238655f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + // Enable latest features + "lib": ["ESNext", "DOM"], + "target": "ESNext", + "module": "ESNext", + "moduleDetection": "force", + "jsx": "react-jsx", + "allowJs": true, + + // Bundler mode + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "noEmit": true, + + // Best practices + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false + } +}