From 9228f3709d61c84c47b1960296893671a023a1df Mon Sep 17 00:00:00 2001 From: Saihajpreet Singh Date: Mon, 27 May 2024 15:28:27 -0400 Subject: [PATCH] use cf rate limiter --- examples/nodejs-cf-worker/.prettierrc | 8 +- examples/nodejs-cf-worker/README.md | 24 +- examples/nodejs-cf-worker/bun.lockb | Bin 38788 -> 39124 bytes examples/nodejs-cf-worker/package.json | 44 +- examples/nodejs-cf-worker/pnpm-lock.yaml | 878 ++++++++++++++++++ examples/nodejs-cf-worker/src/index.ts | 182 ++-- examples/nodejs-cf-worker/tsconfig.json | 184 ++-- .../worker-configuration.d.ts | 8 +- examples/nodejs-cf-worker/wrangler.toml | 13 +- 9 files changed, 1098 insertions(+), 243 deletions(-) create mode 100644 examples/nodejs-cf-worker/pnpm-lock.yaml diff --git a/examples/nodejs-cf-worker/.prettierrc b/examples/nodejs-cf-worker/.prettierrc index 5c7b5d3..8e2655a 100644 --- a/examples/nodejs-cf-worker/.prettierrc +++ b/examples/nodejs-cf-worker/.prettierrc @@ -1,6 +1,6 @@ { - "printWidth": 140, - "singleQuote": true, - "semi": true, - "useTabs": true + "printWidth": 140, + "singleQuote": true, + "semi": true, + "useTabs": false } diff --git a/examples/nodejs-cf-worker/README.md b/examples/nodejs-cf-worker/README.md index 0584630..79c975a 100644 --- a/examples/nodejs-cf-worker/README.md +++ b/examples/nodejs-cf-worker/README.md @@ -45,13 +45,13 @@ curl http://localhost:8787 -H 'Content-Type: application/json' -d '{"query": "{_ ```json5 { - data: { - _meta: { - block: { - number: 202710879, - }, - }, - }, + data: { + _meta: { + block: { + number: 202710879, + }, + }, + }, } ``` @@ -63,11 +63,11 @@ curl http://localhost:8787 -H 'Content-Type: application/json' -d '{"query": "qu ```json5 { - data: { - subgraph: { - id: '8SxuHUYYBLHs1UkgFFYNaS7MgrEiAMbDyt5YzwZsSa6R', - }, - }, + data: { + subgraph: { + id: '8SxuHUYYBLHs1UkgFFYNaS7MgrEiAMbDyt5YzwZsSa6R', + }, + }, } ``` diff --git a/examples/nodejs-cf-worker/bun.lockb b/examples/nodejs-cf-worker/bun.lockb index e7e03d0c2630842b63768c74526e901d94648bcf..ec420d0484515120d8b5a941c5ea0632dc062873 100755 GIT binary patch delta 2808 zcmc&0YfPI}^xm&@K%uk*CN1db;zkRs-=GYFihvo80G%+h3BJ$)U!f1$+0rsh+(+ZO zkQo=)Nf4Y%%+NTqgt;~0F=ECN@P|en$%1S!*SMKEA3w+p5+CTfE#Jca7$0+-^!D8I zxc5Bnz27+pPji>fa6NqH+XIF4r&lW`pS2w;ym=;K#9P)1< zRv=dOUg${Nj096oL7ad%0V=4zB5FltZ`*5f{Dh}DQw5N|^H zgNWO#Z345YMVgtC!x+_biv+%=1>CnJn93E<*sG|(gd^~bti;fZR0dK7h?!UW+(LW1 zRdA!Zu&Kl=9&KOC#4t?AG%?14>))4`i5CWEWwONihMd~7*<)`UK0l_Oo4+2Q@I-V< zu6^op8Ct&s=9-C9$2IH7JB>5W)qIRF4E11*E{SbKQ6XCAAUCEEZbg@Hk8+R|T|8)r z(J0^7MT9b3fC`Fi2&rNrQ@0)3bs9>70bQI7x*twnO^#-GA)v3K98Bx$s0=a@!E=c5G0cy>#IAq1oBjK1u4^@v9fUo6kxbYV>I4x=$$jUpoFx z`lh153tydT*6Bw-blocNsu{NjN~S{S3nj~{WpvyE{)#$zIB-~~ND^6?UK|oc;Y8xG zu%!#~7Bb^8Xr^}$dAsiQhFvgGse#GLWE^Vvtx|KeD*12z)EzFjU2r!Oojh{spvbI& zQgia^AxhW$0la|hF|Z^_SGmby842FOuZVedLL2Wq8G|7)jxMjQH+=#kEa85!dM4r7Vcy>%V5{ z_lRqH`^nhuzj$_0_+gNSbWH36B30Tqb%d}!0$F$SAh$9vxU}o(BnV~XDtcBLk9RFl zFBGxzy!=N5*g__}xT4Y88XOXMO4H%8<#k0r>pc*jx51E*5zBN~kI)PQEsx0~CG~Pk z9*qKJ>(5v&<<@FNkBu$Be!vF}*0NN|QK{g^(1twT#OD(NC#>6OFDzKKbOhpTTJ9== z44Va84LD*mr7hwfDva!;Yi4}!F=hxb_`8@8$YW90r&(aZ(PN$li{O%W{s3e(03G2nkcI!ZDzTbcnFgmrA50*Q} z*D30K=sv=%58}PMHW{0DX1 z#)z@~fj=hFL^34iGm!<8U}2JV8#D2p2(iS+d9N)Z{&$jl&;8xs@0@$zz30A%7nqv! zOs#S9H%<4!O9>-4Hy*NfG#9{N=A^H>hR)-~-R(BId)TX{Pjy5xhrb|^&#{LfZlZ)JkoO8ztBX<5zz{MF@pJS_^cMfM>X>{4qG$p7 z;pj6Ui|Vtuu%u|UP*IMdafrtvdluug==GRKhhB|-H2S5uR04W;iCfy94Y9bC8Ct2H znMk3RrZJ;wAf8F1is&%e56fArp$*edLTMU$aaXvEv_#C)N^PC9?c%hwzSj#gw_Sra zc1%-{Wfl9bwyL|H_3fgNs<*-ije-&wlw0T?m?^hXKX|c!1g&ywQ+m`GdIY>l^HA|N zIWeF~k+Cq4jO+h~NqRRNHt>{z9r^;w!V`S~_zWt@Fz|t(K{X!cFXDk$Cn;pOFVSSM zSe~qkob4U_mT2%V;UKSm1+10JpqW=gBQJycB`FgA#A|Ro75N%$8>BgNc4%&n-Ynr7 z#0%?v(l{k2qPI!-c#h$ZcrnM{Ef3x#M^PEftv!A!i0 z@!x-hOgvPP=?K$noPidHkwVbvQ`R~~mXQ1sXmLzXhzhaR88}ruYlwIwEc6s}ltOID z7rZ=GX|B>&g41YB6*x*W;by5hFY-VlrNq#coYBM?(@7f&#p3H#pXM9R-PnT6bfd}0 z5z-%KuFTGUf2k|DIn0>wx+xgT99YdzS7w?q5er}hW;i1}zWiXFDhYKaBjzB)jEq>& zbV`)Xe{%T!Fq2A%1-_MOb&)sH^WwzLch}PoAfJkn$S;Ldmv&U7#DcfTj_ji|YZ)p) zp^H=2U|tpGjbq@L%S1W2>*8nzP`8#Y03G)EFvC5c7Q!a?M`{6gxmQ<+&o>%Fd_zLd z_+Ia=16.13' } + + '@cloudflare/workerd-darwin-64@1.20240512.0': + resolution: { integrity: sha512-VMp+CsSHFALQiBzPdQ5dDI4T1qwLu0mQ0aeKVNDosXjueN0f3zj/lf+mFil5/9jBbG3t4mG0y+6MMnalP9Lobw== } + engines: { node: '>=16' } + cpu: [x64] + os: [darwin] + + '@cloudflare/workerd-darwin-arm64@1.20240512.0': + resolution: { integrity: sha512-lZktXGmzMrB5rJqY9+PmnNfv1HKlj/YLZwMjPfF0WVKHUFdvQbAHsi7NlKv6mW9uIvlZnS+K4sIkWc0MDXcRnA== } + engines: { node: '>=16' } + cpu: [arm64] + os: [darwin] + + '@cloudflare/workerd-linux-64@1.20240512.0': + resolution: { integrity: sha512-wrHvqCZZqXz6Y3MUTn/9pQNsvaoNjbJpuA6vcXsXu8iCzJi911iVW2WUEBX+MpUWD+mBIP0oXni5tTlhkokOPw== } + engines: { node: '>=16' } + cpu: [x64] + os: [linux] + + '@cloudflare/workerd-linux-arm64@1.20240512.0': + resolution: { integrity: sha512-YPezHMySL9J9tFdzxz390eBswQ//QJNYcZolz9Dgvb3FEfdpK345cE/bsWbMOqw5ws2f82l388epoenghtYvAg== } + engines: { node: '>=16' } + cpu: [arm64] + os: [linux] + + '@cloudflare/workerd-windows-64@1.20240512.0': + resolution: { integrity: sha512-SxKapDrIYSscMR7lGIp/av0l6vokjH4xQ9ACxHgXh+OdOus9azppSmjaPyw4/ePvg7yqpkaNjf9o258IxWtvKQ== } + engines: { node: '>=16' } + cpu: [x64] + os: [win32] + + '@cloudflare/workers-types@4.20240512.0': + resolution: { integrity: sha512-o2yTEWg+YK/I1t/Me+dA0oarO0aCbjibp6wSeaw52DSE9tDyKJ7S+Qdyw/XsMrKn4t8kF6f/YOba+9O4MJfW9w== } + + '@cspotcode/source-map-support@0.8.1': + resolution: { integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== } + engines: { node: '>=12' } + + '@esbuild-plugins/node-globals-polyfill@0.2.3': + resolution: { integrity: sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw== } + peerDependencies: + esbuild: '*' + + '@esbuild-plugins/node-modules-polyfill@0.2.2': + resolution: { integrity: sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA== } + peerDependencies: + esbuild: '*' + + '@esbuild/android-arm64@0.17.19': + resolution: { integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA== } + engines: { node: '>=12' } + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.17.19': + resolution: { integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A== } + engines: { node: '>=12' } + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.17.19': + resolution: { integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww== } + engines: { node: '>=12' } + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.17.19': + resolution: { integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg== } + engines: { node: '>=12' } + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.17.19': + resolution: { integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw== } + engines: { node: '>=12' } + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.17.19': + resolution: { integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ== } + engines: { node: '>=12' } + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.17.19': + resolution: { integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ== } + engines: { node: '>=12' } + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.17.19': + resolution: { integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg== } + engines: { node: '>=12' } + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.17.19': + resolution: { integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA== } + engines: { node: '>=12' } + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.17.19': + resolution: { integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ== } + engines: { node: '>=12' } + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.17.19': + resolution: { integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ== } + engines: { node: '>=12' } + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.17.19': + resolution: { integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A== } + engines: { node: '>=12' } + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.17.19': + resolution: { integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg== } + engines: { node: '>=12' } + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.17.19': + resolution: { integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA== } + engines: { node: '>=12' } + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.17.19': + resolution: { integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q== } + engines: { node: '>=12' } + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.17.19': + resolution: { integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw== } + engines: { node: '>=12' } + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.17.19': + resolution: { integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q== } + engines: { node: '>=12' } + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-x64@0.17.19': + resolution: { integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g== } + engines: { node: '>=12' } + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.17.19': + resolution: { integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg== } + engines: { node: '>=12' } + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.17.19': + resolution: { integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag== } + engines: { node: '>=12' } + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.17.19': + resolution: { integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw== } + engines: { node: '>=12' } + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.17.19': + resolution: { integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA== } + engines: { node: '>=12' } + cpu: [x64] + os: [win32] + + '@fastify/busboy@2.1.1': + resolution: { integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA== } + engines: { node: '>=14' } + + '@jridgewell/resolve-uri@3.1.2': + resolution: { integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== } + engines: { node: '>=6.0.0' } + + '@jridgewell/sourcemap-codec@1.4.15': + resolution: { integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== } + + '@jridgewell/trace-mapping@0.3.9': + resolution: { integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== } + + '@types/node-forge@1.3.11': + resolution: { integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ== } + + '@types/node@20.12.12': + resolution: { integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw== } + + acorn-walk@8.3.2: + resolution: { integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== } + engines: { node: '>=0.4.0' } + + acorn@8.11.3: + resolution: { integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== } + engines: { node: '>=0.4.0' } + hasBin: true + + anymatch@3.1.3: + resolution: { integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== } + engines: { node: '>= 8' } + + as-table@1.0.55: + resolution: { integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ== } + + binary-extensions@2.3.0: + resolution: { integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== } + engines: { node: '>=8' } + + blake3-wasm@2.1.5: + resolution: { integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g== } + + braces@3.0.3: + resolution: { integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== } + engines: { node: '>=8' } + + capnp-ts@0.7.0: + resolution: { integrity: sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g== } + + chokidar@3.6.0: + resolution: { integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== } + engines: { node: '>= 8.10.0' } + + cookie@0.5.0: + resolution: { integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== } + engines: { node: '>= 0.6' } + + data-uri-to-buffer@2.0.2: + resolution: { integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA== } + + debug@4.3.4: + resolution: { integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== } + engines: { node: '>=6.0' } + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + esbuild@0.17.19: + resolution: { integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw== } + engines: { node: '>=12' } + hasBin: true + + escape-string-regexp@4.0.0: + resolution: { integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== } + engines: { node: '>=10' } + + estree-walker@0.6.1: + resolution: { integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w== } + + exit-hook@2.2.1: + resolution: { integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw== } + engines: { node: '>=6' } + + fill-range@7.1.1: + resolution: { integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== } + engines: { node: '>=8' } + + fsevents@2.3.3: + resolution: { integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== } + engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } + os: [darwin] + + function-bind@1.1.2: + resolution: { integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== } + + get-source@2.0.12: + resolution: { integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w== } + + glob-parent@5.1.2: + resolution: { integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== } + engines: { node: '>= 6' } + + glob-to-regexp@0.4.1: + resolution: { integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== } + + hasown@2.0.2: + resolution: { integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== } + engines: { node: '>= 0.4' } + + is-binary-path@2.1.0: + resolution: { integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== } + engines: { node: '>=8' } + + is-core-module@2.13.1: + resolution: { integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== } + + is-extglob@2.1.1: + resolution: { integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== } + engines: { node: '>=0.10.0' } + + is-glob@4.0.3: + resolution: { integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== } + engines: { node: '>=0.10.0' } + + is-number@7.0.0: + resolution: { integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== } + engines: { node: '>=0.12.0' } + + magic-string@0.25.9: + resolution: { integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ== } + + mime@3.0.0: + resolution: { integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== } + engines: { node: '>=10.0.0' } + hasBin: true + + miniflare@3.20240512.0: + resolution: { integrity: sha512-X0PlKR0AROKpxFoJNmRtCMIuJxj+ngEcyTOlEokj2rAQ0TBwUhB4/1uiPvdI6ofW5NugPOD1uomAv+gLjwsLDQ== } + engines: { node: '>=16.13' } + hasBin: true + + ms@2.1.2: + resolution: { integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== } + + mustache@4.2.0: + resolution: { integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ== } + hasBin: true + + nanoid@3.3.7: + resolution: { integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== } + engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 } + hasBin: true + + node-forge@1.3.1: + resolution: { integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== } + engines: { node: '>= 6.13.0' } + + normalize-path@3.0.0: + resolution: { integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== } + engines: { node: '>=0.10.0' } + + path-parse@1.0.7: + resolution: { integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== } + + path-to-regexp@6.2.2: + resolution: { integrity: sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw== } + + picomatch@2.3.1: + resolution: { integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== } + engines: { node: '>=8.6' } + + prettier@3.2.5: + resolution: { integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== } + engines: { node: '>=14' } + hasBin: true + + printable-characters@1.0.42: + resolution: { integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ== } + + readdirp@3.6.0: + resolution: { integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== } + engines: { node: '>=8.10.0' } + + resolve.exports@2.0.2: + resolution: { integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== } + engines: { node: '>=10' } + + resolve@1.22.8: + resolution: { integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== } + hasBin: true + + rollup-plugin-inject@3.0.2: + resolution: { integrity: sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w== } + deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject. + + rollup-plugin-node-polyfills@0.2.1: + resolution: { integrity: sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA== } + + rollup-pluginutils@2.8.2: + resolution: { integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ== } + + selfsigned@2.4.1: + resolution: { integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q== } + engines: { node: '>=10' } + + source-map@0.6.1: + resolution: { integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== } + engines: { node: '>=0.10.0' } + + sourcemap-codec@1.4.8: + resolution: { integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== } + deprecated: Please use @jridgewell/sourcemap-codec instead + + stacktracey@2.1.8: + resolution: { integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw== } + + stoppable@1.1.0: + resolution: { integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw== } + engines: { node: '>=4', npm: '>=6' } + + supports-preserve-symlinks-flag@1.0.0: + resolution: { integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== } + engines: { node: '>= 0.4' } + + to-regex-range@5.0.1: + resolution: { integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== } + engines: { node: '>=8.0' } + + tslib@2.6.2: + resolution: { integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== } + + typescript@5.4.5: + resolution: { integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== } + engines: { node: '>=14.17' } + hasBin: true + + undici-types@5.26.5: + resolution: { integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== } + + undici@5.28.4: + resolution: { integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g== } + engines: { node: '>=14.0' } + + workerd@1.20240512.0: + resolution: { integrity: sha512-VUBmR1PscAPHEE0OF/G2K7/H1gnr9aDWWZzdkIgWfNKkv8dKFCT75H+GJtUHjfwqz3rYCzaNZmatSXOpLGpF8A== } + engines: { node: '>=16' } + hasBin: true + + wrangler@3.57.1: + resolution: { integrity: sha512-M8YnWUwdrb8AFiRePtVnzlDn02OX4osWvdl8oVh6eyZqqkqXYg7lwlYBr14Qj92pMN4JvMBmDZoukkYHvwpJRg== } + engines: { node: '>=16.17.0' } + hasBin: true + peerDependencies: + '@cloudflare/workers-types': ^4.20240512.0 + peerDependenciesMeta: + '@cloudflare/workers-types': + optional: true + + ws@8.17.0: + resolution: { integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow== } + engines: { node: '>=10.0.0' } + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xxhash-wasm@1.0.2: + resolution: { integrity: sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A== } + + youch@3.3.3: + resolution: { integrity: sha512-qSFXUk3UZBLfggAW3dJKg0BMblG5biqSF8M34E06o5CSsZtH92u9Hqmj2RzGiHDi64fhe83+4tENFP2DB6t6ZA== } + + zod@3.23.8: + resolution: { integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g== } + +snapshots: + '@cloudflare/kv-asset-handler@0.3.2': + dependencies: + mime: 3.0.0 + + '@cloudflare/workerd-darwin-64@1.20240512.0': + optional: true + + '@cloudflare/workerd-darwin-arm64@1.20240512.0': + optional: true + + '@cloudflare/workerd-linux-64@1.20240512.0': + optional: true + + '@cloudflare/workerd-linux-arm64@1.20240512.0': + optional: true + + '@cloudflare/workerd-windows-64@1.20240512.0': + optional: true + + '@cloudflare/workers-types@4.20240512.0': {} + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + '@esbuild-plugins/node-globals-polyfill@0.2.3(esbuild@0.17.19)': + dependencies: + esbuild: 0.17.19 + + '@esbuild-plugins/node-modules-polyfill@0.2.2(esbuild@0.17.19)': + dependencies: + esbuild: 0.17.19 + escape-string-regexp: 4.0.0 + rollup-plugin-node-polyfills: 0.2.1 + + '@esbuild/android-arm64@0.17.19': + optional: true + + '@esbuild/android-arm@0.17.19': + optional: true + + '@esbuild/android-x64@0.17.19': + optional: true + + '@esbuild/darwin-arm64@0.17.19': + optional: true + + '@esbuild/darwin-x64@0.17.19': + optional: true + + '@esbuild/freebsd-arm64@0.17.19': + optional: true + + '@esbuild/freebsd-x64@0.17.19': + optional: true + + '@esbuild/linux-arm64@0.17.19': + optional: true + + '@esbuild/linux-arm@0.17.19': + optional: true + + '@esbuild/linux-ia32@0.17.19': + optional: true + + '@esbuild/linux-loong64@0.17.19': + optional: true + + '@esbuild/linux-mips64el@0.17.19': + optional: true + + '@esbuild/linux-ppc64@0.17.19': + optional: true + + '@esbuild/linux-riscv64@0.17.19': + optional: true + + '@esbuild/linux-s390x@0.17.19': + optional: true + + '@esbuild/linux-x64@0.17.19': + optional: true + + '@esbuild/netbsd-x64@0.17.19': + optional: true + + '@esbuild/openbsd-x64@0.17.19': + optional: true + + '@esbuild/sunos-x64@0.17.19': + optional: true + + '@esbuild/win32-arm64@0.17.19': + optional: true + + '@esbuild/win32-ia32@0.17.19': + optional: true + + '@esbuild/win32-x64@0.17.19': + optional: true + + '@fastify/busboy@2.1.1': {} + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.4.15': {} + + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + + '@types/node-forge@1.3.11': + dependencies: + '@types/node': 20.12.12 + + '@types/node@20.12.12': + dependencies: + undici-types: 5.26.5 + + acorn-walk@8.3.2: {} + + acorn@8.11.3: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + as-table@1.0.55: + dependencies: + printable-characters: 1.0.42 + + binary-extensions@2.3.0: {} + + blake3-wasm@2.1.5: {} + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + capnp-ts@0.7.0: + dependencies: + debug: 4.3.4 + tslib: 2.6.2 + transitivePeerDependencies: + - supports-color + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + cookie@0.5.0: {} + + data-uri-to-buffer@2.0.2: {} + + debug@4.3.4: + dependencies: + ms: 2.1.2 + + esbuild@0.17.19: + optionalDependencies: + '@esbuild/android-arm': 0.17.19 + '@esbuild/android-arm64': 0.17.19 + '@esbuild/android-x64': 0.17.19 + '@esbuild/darwin-arm64': 0.17.19 + '@esbuild/darwin-x64': 0.17.19 + '@esbuild/freebsd-arm64': 0.17.19 + '@esbuild/freebsd-x64': 0.17.19 + '@esbuild/linux-arm': 0.17.19 + '@esbuild/linux-arm64': 0.17.19 + '@esbuild/linux-ia32': 0.17.19 + '@esbuild/linux-loong64': 0.17.19 + '@esbuild/linux-mips64el': 0.17.19 + '@esbuild/linux-ppc64': 0.17.19 + '@esbuild/linux-riscv64': 0.17.19 + '@esbuild/linux-s390x': 0.17.19 + '@esbuild/linux-x64': 0.17.19 + '@esbuild/netbsd-x64': 0.17.19 + '@esbuild/openbsd-x64': 0.17.19 + '@esbuild/sunos-x64': 0.17.19 + '@esbuild/win32-arm64': 0.17.19 + '@esbuild/win32-ia32': 0.17.19 + '@esbuild/win32-x64': 0.17.19 + + escape-string-regexp@4.0.0: {} + + estree-walker@0.6.1: {} + + exit-hook@2.2.1: {} + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + get-source@2.0.12: + dependencies: + data-uri-to-buffer: 2.0.2 + source-map: 0.6.1 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-to-regexp@0.4.1: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-core-module@2.13.1: + dependencies: + hasown: 2.0.2 + + is-extglob@2.1.1: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + + magic-string@0.25.9: + dependencies: + sourcemap-codec: 1.4.8 + + mime@3.0.0: {} + + miniflare@3.20240512.0: + dependencies: + '@cspotcode/source-map-support': 0.8.1 + acorn: 8.11.3 + acorn-walk: 8.3.2 + capnp-ts: 0.7.0 + exit-hook: 2.2.1 + glob-to-regexp: 0.4.1 + stoppable: 1.1.0 + undici: 5.28.4 + workerd: 1.20240512.0 + ws: 8.17.0 + youch: 3.3.3 + zod: 3.23.8 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + ms@2.1.2: {} + + mustache@4.2.0: {} + + nanoid@3.3.7: {} + + node-forge@1.3.1: {} + + normalize-path@3.0.0: {} + + path-parse@1.0.7: {} + + path-to-regexp@6.2.2: {} + + picomatch@2.3.1: {} + + prettier@3.2.5: {} + + printable-characters@1.0.42: {} + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + resolve.exports@2.0.2: {} + + resolve@1.22.8: + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + rollup-plugin-inject@3.0.2: + dependencies: + estree-walker: 0.6.1 + magic-string: 0.25.9 + rollup-pluginutils: 2.8.2 + + rollup-plugin-node-polyfills@0.2.1: + dependencies: + rollup-plugin-inject: 3.0.2 + + rollup-pluginutils@2.8.2: + dependencies: + estree-walker: 0.6.1 + + selfsigned@2.4.1: + dependencies: + '@types/node-forge': 1.3.11 + node-forge: 1.3.1 + + source-map@0.6.1: {} + + sourcemap-codec@1.4.8: {} + + stacktracey@2.1.8: + dependencies: + as-table: 1.0.55 + get-source: 2.0.12 + + stoppable@1.1.0: {} + + supports-preserve-symlinks-flag@1.0.0: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + tslib@2.6.2: {} + + typescript@5.4.5: {} + + undici-types@5.26.5: {} + + undici@5.28.4: + dependencies: + '@fastify/busboy': 2.1.1 + + workerd@1.20240512.0: + optionalDependencies: + '@cloudflare/workerd-darwin-64': 1.20240512.0 + '@cloudflare/workerd-darwin-arm64': 1.20240512.0 + '@cloudflare/workerd-linux-64': 1.20240512.0 + '@cloudflare/workerd-linux-arm64': 1.20240512.0 + '@cloudflare/workerd-windows-64': 1.20240512.0 + + wrangler@3.57.1(@cloudflare/workers-types@4.20240512.0): + dependencies: + '@cloudflare/kv-asset-handler': 0.3.2 + '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19) + '@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19) + blake3-wasm: 2.1.5 + chokidar: 3.6.0 + esbuild: 0.17.19 + miniflare: 3.20240512.0 + nanoid: 3.3.7 + path-to-regexp: 6.2.2 + resolve: 1.22.8 + resolve.exports: 2.0.2 + selfsigned: 2.4.1 + source-map: 0.6.1 + xxhash-wasm: 1.0.2 + optionalDependencies: + '@cloudflare/workers-types': 4.20240512.0 + fsevents: 2.3.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + ws@8.17.0: {} + + xxhash-wasm@1.0.2: {} + + youch@3.3.3: + dependencies: + cookie: 0.5.0 + mustache: 4.2.0 + stacktracey: 2.1.8 + + zod@3.23.8: {} diff --git a/examples/nodejs-cf-worker/src/index.ts b/examples/nodejs-cf-worker/src/index.ts index a5bd8f6..d67b1c2 100644 --- a/examples/nodejs-cf-worker/src/index.ts +++ b/examples/nodejs-cf-worker/src/index.ts @@ -24,113 +24,79 @@ * @see https://developers.cloudflare.com/workers/configuration/secrets/ */ -import { DurableObject } from 'cloudflare:workers'; -import { z } from 'zod'; - -// const WHITEGLOVE_MAP = { -// "api.thegraph.com/subgraphs/name/schmidsi/anudit-lens": { -// "" -// "rateLimit": 100, -// "rateLimitWindow": 6 -// } -// } - -const GraphqlReqSchema = z.object({ - query: z.string().min(1), - operationName: z.string().optional().nullable(), - variables: z.record(z.unknown()).optional().nullable(), -}); - export default { - // The fetch handler is invoked when this worker receives a HTTP(S) request - // and should return a Response (optionally wrapped in a Promise) - async fetch(req: Request, env: Env): Promise { - // The Graph Network Subgraph GraphQL requests should only support: OPTIONS, POST requests - if (!['POST', 'OPTIONS'].includes(req.method.toUpperCase())) { - return new Response('Unsupported', { status: 400 }); - } - - // TODO: per subgraph rate limiting - const id = env.RATE_LIMITER.idFromName('global'); - - console.log('Hello Pranav'); - - try { - const stub = env.RATE_LIMITER.get(id); - // const milliseconds_to_next_request = await ; - - // console.log(milliseconds_to_next_request, 'milliseconds_to_next_request') - - if (await stub.rateLimit()) { - // Alternatively one could sleep for the necessary length of time - return new Response( - JSON.stringify({ - errors: [ - { - message: - 'Rate limit on ENS communtiy key exceeded. Try again later or got to https://thegraph.com/studio to create your own API key. Find the ENS subgraph here: https://thegraph.com/explorer/subgraphs/5XqPmWe6gjyrJtFn9cLy237i4cWw2j9HcUJEXsP5qGtH?v=1&view=Overview&chain=arbitrum-one', - }, - ], - }), - { status: 429 } - ); - } - } catch (error) { - console.log(error, 'error') - return new Response('Could not connect to rate limiter', { status: 502 }); - } - - const response = await querySubgraph(req, env); - if (response.status !== 200) { - return new Response(response.statusText, { status: response.status }); - } - const body = await response.json(); - - return new Response(JSON.stringify(body), { headers: { 'Content-Type': 'application/json' }, status: 200 }); - }, + // The fetch handler is invoked when this worker receives a HTTP(S) request + // and should return a Response (optionally wrapped in a Promise) + async fetch(req: Request, env: Env): Promise { + const url = new URL(req.url); + const path = url.pathname; + + // The Graph Network Subgraph GraphQL requests should only support: OPTIONS, POST requests + if (!['POST', 'OPTIONS'].includes(req.method.toUpperCase())) { + return new Response('Unsupported', { status: 400 }); + } + + // register path called by admin to set the network subgraph url for a given path + if (req.method === 'POST' && path === '/register') { + if (req.headers.get('Authorization') !== `${env.ADMIN_ACCESS_KEY}`) { + return new Response('Unauthorized', { status: 401 }); + } + const body = await req.json(); + + const { to, from } = body as { to: string; from: string }; + + if (!to || !from) { + return new Response('Invalid request', { status: 400 }); + } + + const hostedSubgraph = new URL(to); + const allowedHosts = ['api.thegraph.com']; + if (!allowedHosts.includes(hostedSubgraph.host)) { + return new Response(`Invalid URL for hosted service subgraph.`, { status: 400 }); + } + + const networkSubgraphUrl = new URL(from); + const allowedNetworkSubgraphs = ['api.thegraph.com', 'gateway-arbitrum.network.thegraph.com', 'gateway.network.thegraph.com']; + if (!allowedNetworkSubgraphs.includes(networkSubgraphUrl.host)) { + return new Response(`Invalid URL for network subgraph.`, { status: 400 }); + } + + await env.redirect_limit_store.put(hostedSubgraph.pathname, networkSubgraphUrl.toString()); + + return new Response('Network subgraph registered', { status: 200 }); + } + + const networkSubgraphUrl = await env.redirect_limit_store.get(path); + + if (!networkSubgraphUrl) { + return new Response(`No network subgraph found for ${url.toString()}. Contact support team.`, { status: 404 }); + } + + const { success } = await env.RATE_LIMITER.limit({ key: path }); + + if (!success) { + // TODO: improve error message + return new Response( + JSON.stringify({ + errors: [ + { + message: + 'Rate limit on ENS communtiy key exceeded. Try again later or got to https://thegraph.com/studio to create your own API key. Find the ENS subgraph here: https://thegraph.com/explorer/subgraphs/5XqPmWe6gjyrJtFn9cLy237i4cWw2j9HcUJEXsP5qGtH?v=1&view=Overview&chain=arbitrum-one', + }, + ], + }), + { status: 429 }, + ); + } + + return fetch(networkSubgraphUrl, { + method: 'POST', + body: req.body, + headers: { + ...req.headers, + 'Content-Type': 'application/json', + 'X-Forwarded-For': 'Graph Rate Limiter', + }, + }); + }, }; - -async function querySubgraph(req: Request, env: Env) { - const body = await req.json(); - if (body == null) { - return new Response('Invalid GraphQL Request', { status: 400 }); - } - const parsedGqlRequest = GraphqlReqSchema.safeParse(body); - if (!parsedGqlRequest.success) { - return new Response('Invalid GraphQL Request', { status: 400 }); - } - const gqlRequest = parsedGqlRequest.data; - - return await fetch(env.SUBGRAPH_ENDPOINT, { - method: 'POST', - body: JSON.stringify(gqlRequest), - headers: { - // authorization: `Bearer ${env.API_KEY}`, - 'Content-Type': 'application/json', - }, - }); -} - -export class RateLimiter extends DurableObject { - static milliseconds_per_request = 10000; - - lastRequest: number; - - constructor(ctx: DurableObjectState, env: Env) { - super(ctx, env); - this.lastRequest = 0; - } - - async rateLimit(): Promise { - const now = Date.now(); - - console.log(now, this.lastRequest, RateLimiter.milliseconds_per_request); - - if (now - this.lastRequest > RateLimiter.milliseconds_per_request) { - this.lastRequest = now; - return false; - } else { - return true - } - } - } \ No newline at end of file diff --git a/examples/nodejs-cf-worker/tsconfig.json b/examples/nodejs-cf-worker/tsconfig.json index 9cbc80c..cdc93a8 100644 --- a/examples/nodejs-cf-worker/tsconfig.json +++ b/examples/nodejs-cf-worker/tsconfig.json @@ -1,102 +1,102 @@ { - "compilerOptions": { - /* Visit https://aka.ms/tsconfig.json to read more about this file */ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ - /* Projects */ - // "incremental": true, /* Enable incremental compilation */ - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ - // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - /* Language and Environment */ - "target": "ESNext" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, - "lib": ["ESNext"] /* Specify a set of bundled library declaration files that describe the target runtime environment. */, - // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ - // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + /* Language and Environment */ + "target": "ESNext" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + "lib": ["ESNext"] /* Specify a set of bundled library declaration files that describe the target runtime environment. */, + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - /* Modules */ - "module": "NodeNext" /* Specify what module code is generated. */, - // "rootDir": "./", /* Specify the root folder within your source files. */ - "moduleResolution": "NodeNext" /* Specify how TypeScript looks up a file from a given module specifier. */, - // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ - "types": [ - "@cloudflare/workers-types/2023-07-01" - ] /* Specify type package names to be included without being referenced in a source file. */, - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - "resolveJsonModule": true /* Enable importing .json files */, - // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + /* Modules */ + "module": "NodeNext" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + "moduleResolution": "NodeNext" /* Specify how TypeScript looks up a file from a given module specifier. */, + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ + "types": [ + "@cloudflare/workers-types/2023-07-01" + ] /* Specify type package names to be included without being referenced in a source file. */, + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + "resolveJsonModule": true /* Enable importing .json files */, + // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ - /* JavaScript Support */ - "allowJs": true /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */, - "checkJs": false /* Enable error reporting in type-checked JavaScript files. */, - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + /* JavaScript Support */ + "allowJs": true /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */, + "checkJs": false /* Enable error reporting in type-checked JavaScript files. */, + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ - /* Emit */ - // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ - // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ - // "outDir": "./", /* Specify an output folder for all emitted files. */ - // "removeComments": true, /* Disable emitting comments. */ - "noEmit": true /* Disable emitting files from a compilation. */, - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ - // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true /* Disable emitting files from a compilation. */, + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - /* Interop Constraints */ - "isolatedModules": true /* Ensure that each file can be safely transpiled without relying on other imports. */, - "allowSyntheticDefaultImports": true /* Allow 'import x from y' when a module doesn't have a default export. */, - // "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + /* Interop Constraints */ + "isolatedModules": true /* Ensure that each file can be safely transpiled without relying on other imports. */, + "allowSyntheticDefaultImports": true /* Allow 'import x from y' when a module doesn't have a default export. */, + // "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, - /* Type Checking */ - "strict": true /* Enable all strict type-checking options. */, - "noImplicitAny": true /* Enable error reporting for expressions and declarations with an implied `any` type.. */, - "strictNullChecks": true /* When type checking, take into account `null` and `undefined`. */, - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ - // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + "noImplicitAny": true /* Enable error reporting for expressions and declarations with an implied `any` type.. */, + "strictNullChecks": true /* When type checking, take into account `null` and `undefined`. */, + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ - } + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } } diff --git a/examples/nodejs-cf-worker/worker-configuration.d.ts b/examples/nodejs-cf-worker/worker-configuration.d.ts index 06854bc..6c3c9cc 100644 --- a/examples/nodejs-cf-worker/worker-configuration.d.ts +++ b/examples/nodejs-cf-worker/worker-configuration.d.ts @@ -2,7 +2,9 @@ // by running `wrangler types` interface Env { - SUBGRAPH_ENDPOINT: "https://gateway-arbitrum.network.thegraph.com/api/25eb15e49c08702d60d90be66dd9a9a3/subgraphs/id/74z4nnW6cr62ox3fLFaD3muieJzMXJimi6EZsG52yChM"; - API_KEY: string; - RATE_LIMITER: DurableObjectNamespace; + ADMIN_ACCESS_KEY: string; + RATE_LIMITER: { + limit: ({ key: string }) => Promise<{ success: boolean }>; + }; + redirect_limit_store: KVNamespace; } diff --git a/examples/nodejs-cf-worker/wrangler.toml b/examples/nodejs-cf-worker/wrangler.toml index bac35e4..a6aca76 100644 --- a/examples/nodejs-cf-worker/wrangler.toml +++ b/examples/nodejs-cf-worker/wrangler.toml @@ -17,10 +17,19 @@ mode = "smart" # Replace this with your subgraph endpoint [vars] SUBGRAPH_ENDPOINT = "https://gateway-arbitrum.network.thegraph.com/api/25eb15e49c08702d60d90be66dd9a9a3/subgraphs/id/74z4nnW6cr62ox3fLFaD3muieJzMXJimi6EZsG52yChM" +ADMIN_ACCESS_KEY = "CONFIGURE_A_SECRET_KEY_FOR_ADMINS" -[[durable_objects.bindings]] +[[unsafe.bindings]] name = "RATE_LIMITER" -class_name = "RateLimiter" +type = "ratelimit" +namespace_id = "1001" + +# 10 req/sec == 600 req/min +simple = { limit = 600, period = 60 } + +kv_namespaces = [ + { binding = "redirect_limit_store", id = "06779da6940b431db6e566b4846d64db" } +] [[migrations]] tag = "v1"