A very performant and light (2mb in memory) link shortener and tracker. Written in Rust and React and uses Postgres/SQLite.

Compare changes

Choose any two refs to compare.

+3 -1
.env.example
··· 1 - DATABASE_URL=postgresql://user:password@localhost/dbname 1 + # by default, simplelink uses an sqlite db in /data, to use a postgres db, set DATABASE_URl 2 + # DATABASE_URL=postgresql://user:password@localhost/dbname 2 3 SERVER_HOST=127.0.0.1 3 4 SERVER_PORT=8080 5 + JWT_SECRET=change-me-in-production
+5 -15
.github/workflows/docker-image.yml
··· 29 29 30 30 - name: Install cosign 31 31 if: github.event_name != 'pull_request' 32 - uses: sigstore/cosign-installer@v3.7.0 32 + uses: sigstore/cosign-installer@v3.8.1 33 33 with: 34 - cosign-release: "v2.4.1" 34 + cosign-release: "v2.4.3" 35 35 36 36 - name: Setup Docker buildx 37 37 uses: docker/setup-buildx-action@v3 ··· 59 59 ${{ env.IMAGE_NAME }} 60 60 ${{ env.REGISTRY }}/${{ github.repository }} 61 61 62 - - name: Build and push Docker image (amd64) 63 - uses: docker/build-push-action@v6 64 - with: 65 - context: . 66 - file: ./Dockerfile 67 - platforms: linux/amd64 68 - push: ${{ github.event_name != 'pull_request' }} 69 - tags: ${{ steps.meta.outputs.tags }}-amd64 70 - labels: ${{ steps.meta.outputs.labels }} 71 - 72 - - name: Build and push Docker image (arm64) 62 + - name: Build and push Docker image 73 63 uses: docker/build-push-action@v6 74 64 with: 75 65 context: . 76 66 file: ./Dockerfile 77 - platforms: linux/arm64 67 + platforms: linux/amd64,linux/arm64 78 68 push: ${{ github.event_name != 'pull_request' }} 79 - tags: ${{ steps.meta.outputs.tags }}-arm64 69 + tags: ${{ steps.meta.outputs.tags }} 80 70 labels: ${{ steps.meta.outputs.labels }}
+6 -1
.gitignore
··· 6 6 /target 7 7 /release 8 8 release.tar.gz 9 - *.log 9 + *.log 10 + .DS_STORE 11 + admin-setup-token.txt 12 + package-lock.json 13 + bun.lock 14 + *.db*
+121 -220
Cargo.lock
··· 607 607 ] 608 608 609 609 [[package]] 610 - name = "core-foundation" 611 - version = "0.9.4" 612 - source = "registry+https://github.com/rust-lang/crates.io-index" 613 - checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" 614 - dependencies = [ 615 - "core-foundation-sys", 616 - "libc", 617 - ] 618 - 619 - [[package]] 620 610 name = "core-foundation-sys" 621 611 version = "0.8.7" 622 612 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 838 828 checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 839 829 840 830 [[package]] 841 - name = "foreign-types" 842 - version = "0.3.2" 831 + name = "foldhash" 832 + version = "0.1.4" 843 833 source = "registry+https://github.com/rust-lang/crates.io-index" 844 - checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 845 - dependencies = [ 846 - "foreign-types-shared", 847 - ] 848 - 849 - [[package]] 850 - name = "foreign-types-shared" 851 - version = "0.1.1" 852 - source = "registry+https://github.com/rust-lang/crates.io-index" 853 - checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 834 + checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" 854 835 855 836 [[package]] 856 837 name = "form_urlencoded" ··· 859 840 checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 860 841 dependencies = [ 861 842 "percent-encoding", 843 + ] 844 + 845 + [[package]] 846 + name = "futures" 847 + version = "0.3.31" 848 + source = "registry+https://github.com/rust-lang/crates.io-index" 849 + checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" 850 + dependencies = [ 851 + "futures-channel", 852 + "futures-core", 853 + "futures-executor", 854 + "futures-io", 855 + "futures-sink", 856 + "futures-task", 857 + "futures-util", 862 858 ] 863 859 864 860 [[package]] ··· 906 902 checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 907 903 908 904 [[package]] 905 + name = "futures-macro" 906 + version = "0.3.31" 907 + source = "registry+https://github.com/rust-lang/crates.io-index" 908 + checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" 909 + dependencies = [ 910 + "proc-macro2", 911 + "quote", 912 + "syn", 913 + ] 914 + 915 + [[package]] 909 916 name = "futures-sink" 910 917 version = "0.3.31" 911 918 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 923 930 source = "registry+https://github.com/rust-lang/crates.io-index" 924 931 checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 925 932 dependencies = [ 933 + "futures-channel", 926 934 "futures-core", 927 935 "futures-io", 936 + "futures-macro", 928 937 "futures-sink", 929 938 "futures-task", 930 939 "memchr", ··· 983 992 984 993 [[package]] 985 994 name = "hashbrown" 986 - version = "0.14.5" 995 + version = "0.15.2" 987 996 source = "registry+https://github.com/rust-lang/crates.io-index" 988 - checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 997 + checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" 989 998 dependencies = [ 990 - "ahash", 991 999 "allocator-api2", 1000 + "equivalent", 1001 + "foldhash", 992 1002 ] 993 1003 994 1004 [[package]] 995 - name = "hashbrown" 996 - version = "0.15.2" 997 - source = "registry+https://github.com/rust-lang/crates.io-index" 998 - checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" 999 - 1000 - [[package]] 1001 1005 name = "hashlink" 1002 - version = "0.9.1" 1006 + version = "0.10.0" 1003 1007 source = "registry+https://github.com/rust-lang/crates.io-index" 1004 - checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" 1008 + checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" 1005 1009 dependencies = [ 1006 - "hashbrown 0.14.5", 1010 + "hashbrown", 1007 1011 ] 1008 1012 1009 1013 [[package]] ··· 1249 1253 checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" 1250 1254 dependencies = [ 1251 1255 "equivalent", 1252 - "hashbrown 0.15.2", 1256 + "hashbrown", 1253 1257 ] 1254 1258 1255 1259 [[package]] ··· 1414 1418 ] 1415 1419 1416 1420 [[package]] 1417 - name = "minimal-lexical" 1418 - version = "0.2.1" 1419 - source = "registry+https://github.com/rust-lang/crates.io-index" 1420 - checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 1421 - 1422 - [[package]] 1423 1421 name = "miniz_oxide" 1424 1422 version = "0.8.3" 1425 1423 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1441 1439 ] 1442 1440 1443 1441 [[package]] 1444 - name = "native-tls" 1445 - version = "0.2.12" 1446 - source = "registry+https://github.com/rust-lang/crates.io-index" 1447 - checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" 1448 - dependencies = [ 1449 - "libc", 1450 - "log", 1451 - "openssl", 1452 - "openssl-probe", 1453 - "openssl-sys", 1454 - "schannel", 1455 - "security-framework", 1456 - "security-framework-sys", 1457 - "tempfile", 1458 - ] 1459 - 1460 - [[package]] 1461 - name = "nom" 1462 - version = "7.1.3" 1463 - source = "registry+https://github.com/rust-lang/crates.io-index" 1464 - checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 1465 - dependencies = [ 1466 - "memchr", 1467 - "minimal-lexical", 1468 - ] 1469 - 1470 - [[package]] 1471 1442 name = "nu-ansi-term" 1472 - version = "0.46.0" 1443 + version = "0.50.1" 1473 1444 source = "registry+https://github.com/rust-lang/crates.io-index" 1474 - checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" 1445 + checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" 1475 1446 dependencies = [ 1476 - "overload", 1477 - "winapi", 1447 + "windows-sys 0.52.0", 1478 1448 ] 1479 1449 1480 1450 [[package]] ··· 1554 1524 version = "1.20.2" 1555 1525 source = "registry+https://github.com/rust-lang/crates.io-index" 1556 1526 checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" 1557 - 1558 - [[package]] 1559 - name = "openssl" 1560 - version = "0.10.68" 1561 - source = "registry+https://github.com/rust-lang/crates.io-index" 1562 - checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" 1563 - dependencies = [ 1564 - "bitflags", 1565 - "cfg-if", 1566 - "foreign-types", 1567 - "libc", 1568 - "once_cell", 1569 - "openssl-macros", 1570 - "openssl-sys", 1571 - ] 1572 - 1573 - [[package]] 1574 - name = "openssl-macros" 1575 - version = "0.1.1" 1576 - source = "registry+https://github.com/rust-lang/crates.io-index" 1577 - checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 1578 - dependencies = [ 1579 - "proc-macro2", 1580 - "quote", 1581 - "syn", 1582 - ] 1583 - 1584 - [[package]] 1585 - name = "openssl-probe" 1586 - version = "0.1.6" 1587 - source = "registry+https://github.com/rust-lang/crates.io-index" 1588 - checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" 1589 - 1590 - [[package]] 1591 - name = "openssl-sys" 1592 - version = "0.9.104" 1593 - source = "registry+https://github.com/rust-lang/crates.io-index" 1594 - checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" 1595 - dependencies = [ 1596 - "cc", 1597 - "libc", 1598 - "pkg-config", 1599 - "vcpkg", 1600 - ] 1601 - 1602 - [[package]] 1603 - name = "overload" 1604 - version = "0.1.1" 1605 - source = "registry+https://github.com/rust-lang/crates.io-index" 1606 - checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" 1607 1527 1608 1528 [[package]] 1609 1529 name = "parking" ··· 1824 1744 1825 1745 [[package]] 1826 1746 name = "ring" 1827 - version = "0.17.8" 1747 + version = "0.17.13" 1828 1748 source = "registry+https://github.com/rust-lang/crates.io-index" 1829 - checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" 1749 + checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee" 1830 1750 dependencies = [ 1831 1751 "cc", 1832 1752 "cfg-if", 1833 1753 "getrandom", 1834 1754 "libc", 1835 - "spin", 1836 1755 "untrusted", 1837 1756 "windows-sys 0.52.0", 1838 1757 ] ··· 1858 1777 ] 1859 1778 1860 1779 [[package]] 1780 + name = "rust-embed" 1781 + version = "6.8.1" 1782 + source = "registry+https://github.com/rust-lang/crates.io-index" 1783 + checksum = "a36224c3276f8c4ebc8c20f158eca7ca4359c8db89991c4925132aaaf6702661" 1784 + dependencies = [ 1785 + "rust-embed-impl", 1786 + "rust-embed-utils", 1787 + "walkdir", 1788 + ] 1789 + 1790 + [[package]] 1791 + name = "rust-embed-impl" 1792 + version = "6.8.1" 1793 + source = "registry+https://github.com/rust-lang/crates.io-index" 1794 + checksum = "49b94b81e5b2c284684141a2fb9e2a31be90638caf040bf9afbc5a0416afe1ac" 1795 + dependencies = [ 1796 + "proc-macro2", 1797 + "quote", 1798 + "rust-embed-utils", 1799 + "syn", 1800 + "walkdir", 1801 + ] 1802 + 1803 + [[package]] 1804 + name = "rust-embed-utils" 1805 + version = "7.8.1" 1806 + source = "registry+https://github.com/rust-lang/crates.io-index" 1807 + checksum = "9d38ff6bf570dc3bb7100fce9f7b60c33fa71d80e88da3f2580df4ff2bdded74" 1808 + dependencies = [ 1809 + "sha2", 1810 + "walkdir", 1811 + ] 1812 + 1813 + [[package]] 1861 1814 name = "rustc-demangle" 1862 1815 version = "0.1.24" 1863 1816 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1898 1851 checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" 1899 1852 1900 1853 [[package]] 1901 - name = "schannel" 1902 - version = "0.1.27" 1854 + name = "same-file" 1855 + version = "1.0.6" 1903 1856 source = "registry+https://github.com/rust-lang/crates.io-index" 1904 - checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" 1857 + checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 1905 1858 dependencies = [ 1906 - "windows-sys 0.59.0", 1859 + "winapi-util", 1907 1860 ] 1908 1861 1909 1862 [[package]] ··· 1913 1866 checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 1914 1867 1915 1868 [[package]] 1916 - name = "security-framework" 1917 - version = "2.11.1" 1918 - source = "registry+https://github.com/rust-lang/crates.io-index" 1919 - checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" 1920 - dependencies = [ 1921 - "bitflags", 1922 - "core-foundation", 1923 - "core-foundation-sys", 1924 - "libc", 1925 - "security-framework-sys", 1926 - ] 1927 - 1928 - [[package]] 1929 - name = "security-framework-sys" 1930 - version = "2.14.0" 1931 - source = "registry+https://github.com/rust-lang/crates.io-index" 1932 - checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" 1933 - dependencies = [ 1934 - "core-foundation-sys", 1935 - "libc", 1936 - ] 1937 - 1938 - [[package]] 1939 1869 name = "semver" 1940 1870 version = "1.0.25" 1941 1871 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2066 1996 "chrono", 2067 1997 "clap", 2068 1998 "dotenv", 1999 + "futures", 2069 2000 "jsonwebtoken", 2070 2001 "lazy_static", 2002 + "mime_guess", 2071 2003 "rand", 2072 2004 "regex", 2005 + "rust-embed", 2073 2006 "serde", 2074 2007 "serde_json", 2075 2008 "sqlx", ··· 2128 2061 ] 2129 2062 2130 2063 [[package]] 2131 - name = "sqlformat" 2132 - version = "0.2.6" 2133 - source = "registry+https://github.com/rust-lang/crates.io-index" 2134 - checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790" 2135 - dependencies = [ 2136 - "nom", 2137 - "unicode_categories", 2138 - ] 2139 - 2140 - [[package]] 2141 2064 name = "sqlx" 2142 - version = "0.8.1" 2065 + version = "0.8.3" 2143 2066 source = "registry+https://github.com/rust-lang/crates.io-index" 2144 - checksum = "fcfa89bea9500db4a0d038513d7a060566bfc51d46d1c014847049a45cce85e8" 2067 + checksum = "4410e73b3c0d8442c5f99b425d7a435b5ee0ae4167b3196771dd3f7a01be745f" 2145 2068 dependencies = [ 2146 2069 "sqlx-core", 2147 2070 "sqlx-macros", ··· 2152 2075 2153 2076 [[package]] 2154 2077 name = "sqlx-core" 2155 - version = "0.8.1" 2078 + version = "0.8.3" 2156 2079 source = "registry+https://github.com/rust-lang/crates.io-index" 2157 - checksum = "d06e2f2bd861719b1f3f0c7dbe1d80c30bf59e76cf019f07d9014ed7eefb8e08" 2080 + checksum = "6a007b6936676aa9ab40207cde35daab0a04b823be8ae004368c0793b96a61e0" 2158 2081 dependencies = [ 2159 - "atoi", 2160 - "byteorder", 2161 2082 "bytes", 2162 2083 "chrono", 2163 2084 "crc", 2164 2085 "crossbeam-queue", 2165 2086 "either", 2166 2087 "event-listener", 2167 - "futures-channel", 2168 2088 "futures-core", 2169 2089 "futures-intrusive", 2170 2090 "futures-io", 2171 2091 "futures-util", 2172 - "hashbrown 0.14.5", 2092 + "hashbrown", 2173 2093 "hashlink", 2174 - "hex", 2175 2094 "indexmap", 2176 2095 "log", 2177 2096 "memchr", 2178 - "native-tls", 2179 2097 "once_cell", 2180 - "paste", 2181 2098 "percent-encoding", 2182 2099 "serde", 2183 2100 "serde_json", 2184 2101 "sha2", 2185 2102 "smallvec", 2186 - "sqlformat", 2187 - "thiserror 1.0.69", 2103 + "thiserror 2.0.11", 2188 2104 "tokio", 2189 2105 "tokio-stream", 2190 2106 "tracing", 2191 2107 "url", 2192 - "uuid", 2193 2108 ] 2194 2109 2195 2110 [[package]] 2196 2111 name = "sqlx-macros" 2197 - version = "0.8.1" 2112 + version = "0.8.3" 2198 2113 source = "registry+https://github.com/rust-lang/crates.io-index" 2199 - checksum = "2f998a9defdbd48ed005a89362bd40dd2117502f15294f61c8d47034107dbbdc" 2114 + checksum = "3112e2ad78643fef903618d78cf0aec1cb3134b019730edb039b69eaf531f310" 2200 2115 dependencies = [ 2201 2116 "proc-macro2", 2202 2117 "quote", ··· 2207 2122 2208 2123 [[package]] 2209 2124 name = "sqlx-macros-core" 2210 - version = "0.8.1" 2125 + version = "0.8.3" 2211 2126 source = "registry+https://github.com/rust-lang/crates.io-index" 2212 - checksum = "3d100558134176a2629d46cec0c8891ba0be8910f7896abfdb75ef4ab6f4e7ce" 2127 + checksum = "4e9f90acc5ab146a99bf5061a7eb4976b573f560bc898ef3bf8435448dd5e7ad" 2213 2128 dependencies = [ 2214 2129 "dotenvy", 2215 2130 "either", ··· 2233 2148 2234 2149 [[package]] 2235 2150 name = "sqlx-mysql" 2236 - version = "0.8.1" 2151 + version = "0.8.3" 2237 2152 source = "registry+https://github.com/rust-lang/crates.io-index" 2238 - checksum = "936cac0ab331b14cb3921c62156d913e4c15b74fb6ec0f3146bd4ef6e4fb3c12" 2153 + checksum = "4560278f0e00ce64938540546f59f590d60beee33fffbd3b9cd47851e5fff233" 2239 2154 dependencies = [ 2240 2155 "atoi", 2241 2156 "base64 0.22.1", ··· 2269 2184 "smallvec", 2270 2185 "sqlx-core", 2271 2186 "stringprep", 2272 - "thiserror 1.0.69", 2187 + "thiserror 2.0.11", 2273 2188 "tracing", 2274 - "uuid", 2275 2189 "whoami", 2276 2190 ] 2277 2191 2278 2192 [[package]] 2279 2193 name = "sqlx-postgres" 2280 - version = "0.8.1" 2194 + version = "0.8.3" 2281 2195 source = "registry+https://github.com/rust-lang/crates.io-index" 2282 - checksum = "9734dbce698c67ecf67c442f768a5e90a49b2a4d61a9f1d59f73874bd4cf0710" 2196 + checksum = "c5b98a57f363ed6764d5b3a12bfedf62f07aa16e1856a7ddc2a0bb190a959613" 2283 2197 dependencies = [ 2284 2198 "atoi", 2285 2199 "base64 0.22.1", ··· 2291 2205 "etcetera", 2292 2206 "futures-channel", 2293 2207 "futures-core", 2294 - "futures-io", 2295 2208 "futures-util", 2296 2209 "hex", 2297 2210 "hkdf", ··· 2309 2222 "smallvec", 2310 2223 "sqlx-core", 2311 2224 "stringprep", 2312 - "thiserror 1.0.69", 2225 + "thiserror 2.0.11", 2313 2226 "tracing", 2314 - "uuid", 2315 2227 "whoami", 2316 2228 ] 2317 2229 2318 2230 [[package]] 2319 2231 name = "sqlx-sqlite" 2320 - version = "0.8.1" 2232 + version = "0.8.3" 2321 2233 source = "registry+https://github.com/rust-lang/crates.io-index" 2322 - checksum = "a75b419c3c1b1697833dd927bdc4c6545a620bc1bbafabd44e1efbe9afcd337e" 2234 + checksum = "f85ca71d3a5b24e64e1d08dd8fe36c6c95c339a896cc33068148906784620540" 2323 2235 dependencies = [ 2324 2236 "atoi", 2325 2237 "chrono", ··· 2337 2249 "sqlx-core", 2338 2250 "tracing", 2339 2251 "url", 2340 - "uuid", 2341 2252 ] 2342 2253 2343 2254 [[package]] ··· 2513 2424 2514 2425 [[package]] 2515 2426 name = "tokio" 2516 - version = "1.43.0" 2427 + version = "1.43.1" 2517 2428 source = "registry+https://github.com/rust-lang/crates.io-index" 2518 - checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" 2429 + checksum = "492a604e2fd7f814268a378409e6c92b5525d747d10db9a229723f55a417958c" 2519 2430 dependencies = [ 2520 2431 "backtrace", 2521 2432 "bytes", ··· 2610 2521 2611 2522 [[package]] 2612 2523 name = "tracing-subscriber" 2613 - version = "0.3.19" 2524 + version = "0.3.20" 2614 2525 source = "registry+https://github.com/rust-lang/crates.io-index" 2615 - checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" 2526 + checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" 2616 2527 dependencies = [ 2617 2528 "nu-ansi-term", 2618 2529 "sharded-slab", ··· 2662 2573 checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" 2663 2574 2664 2575 [[package]] 2665 - name = "unicode_categories" 2666 - version = "0.1.1" 2667 - source = "registry+https://github.com/rust-lang/crates.io-index" 2668 - checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" 2669 - 2670 - [[package]] 2671 2576 name = "untrusted" 2672 2577 version = "0.9.0" 2673 2578 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2709 2614 checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b" 2710 2615 dependencies = [ 2711 2616 "getrandom", 2712 - "serde", 2713 2617 ] 2714 2618 2715 2619 [[package]] ··· 2735 2639 version = "0.9.5" 2736 2640 source = "registry+https://github.com/rust-lang/crates.io-index" 2737 2641 checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 2642 + 2643 + [[package]] 2644 + name = "walkdir" 2645 + version = "2.5.0" 2646 + source = "registry+https://github.com/rust-lang/crates.io-index" 2647 + checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 2648 + dependencies = [ 2649 + "same-file", 2650 + "winapi-util", 2651 + ] 2738 2652 2739 2653 [[package]] 2740 2654 name = "wasi" ··· 2817 2731 ] 2818 2732 2819 2733 [[package]] 2820 - name = "winapi" 2821 - version = "0.3.9" 2734 + name = "winapi-util" 2735 + version = "0.1.9" 2822 2736 source = "registry+https://github.com/rust-lang/crates.io-index" 2823 - checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 2737 + checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" 2824 2738 dependencies = [ 2825 - "winapi-i686-pc-windows-gnu", 2826 - "winapi-x86_64-pc-windows-gnu", 2739 + "windows-sys 0.59.0", 2827 2740 ] 2828 - 2829 - [[package]] 2830 - name = "winapi-i686-pc-windows-gnu" 2831 - version = "0.4.0" 2832 - source = "registry+https://github.com/rust-lang/crates.io-index" 2833 - checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 2834 - 2835 - [[package]] 2836 - name = "winapi-x86_64-pc-windows-gnu" 2837 - version = "0.4.0" 2838 - source = "registry+https://github.com/rust-lang/crates.io-index" 2839 - checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 2840 2741 2841 2742 [[package]] 2842 2743 name = "windows-core"
+7 -4
Cargo.toml
··· 8 8 path = "src/lib.rs" 9 9 10 10 [dependencies] 11 + rust-embed = "6.8" 11 12 jsonwebtoken = "9" 12 13 actix-web = "4.4" 13 14 actix-files = "0.6" 14 15 actix-cors = "0.6" 15 - tokio = { version = "1.36", features = ["full"] } 16 - sqlx = { version = "0.8", features = ["runtime-tokio-native-tls", "postgres", "uuid", "chrono"] } 16 + tokio = { version = "1.43", features = ["rt-multi-thread", "macros"] } 17 + sqlx = { version = "0.8", features = ["runtime-tokio", "postgres", "sqlite", "chrono"] } 17 18 serde = { version = "1.0", features = ["derive"] } 18 19 serde_json = "1.0" 19 20 anyhow = "1.0" 20 21 thiserror = "1.0" 21 22 tracing = "0.1" 22 23 tracing-subscriber = "0.3" 23 - uuid = { version = "1.7", features = ["v4", "serde"] } 24 + uuid = { version = "1.7", features = ["v4"] } # Remove serde if not using UUID serialization 24 25 base62 = "2.0" 25 26 clap = { version = "4.5", features = ["derive"] } 26 27 dotenv = "0.15" ··· 28 29 regex = "1.10" 29 30 lazy_static = "1.4" 30 31 argon2 = "0.5.3" 31 - rand = { version = "0.8", features = ["std"] } 32 + rand = { version = "0.8", features = ["std"] } 33 + mime_guess = "2.0.5" 34 + futures = "0.3.31"
+2 -2
Dockerfile
··· 4 4 WORKDIR /usr/src/frontend 5 5 6 6 # Copy frontend files 7 - COPY frontend/package*.json ./ 7 + COPY frontend/package.json ./ 8 8 RUN bun install 9 9 10 10 COPY frontend/ ./ ··· 57 57 # Copy static files 58 58 COPY --from=backend-builder /usr/src/app/static /app/static 59 59 60 - # Expose the port (this is just documentation) 60 + # Expose the port 61 61 EXPOSE 8080 62 62 63 63 # Set default network configuration
+80
README.md
··· 1 + # SimpleLink 2 + 3 + A very performant and light (2MB in memory) link shortener and tracker. Written in Rust and React and uses Postgres or SQLite. 4 + 5 + ![MainView](readme_img/mainview.jpg) 6 + 7 + ![StatsView](readme_img/statview.jpg) 8 + 9 + ## How to Run 10 + 11 + ### From Docker 12 + 13 + ```bash 14 + docker run -p 8080:8080 \ 15 + -e JWT_SECRET=change-me-in-production \ 16 + -e SIMPLELINK_USER=admin@example.com \ 17 + -e SIMPLELINK_PASS=your-secure-password \ 18 + -v simplelink_data:/data \ 19 + ghcr.io/waveringana/simplelink:v2.2 20 + ``` 21 + 22 + ### Environment Variables 23 + 24 + - `JWT_SECRET`: Required. Used for JWT token generation 25 + - `SIMPLELINK_USER`: Optional. If set along with SIMPLELINK_PASS, creates an admin user on first run 26 + - `SIMPLELINK_PASS`: Optional. Admin user password 27 + - `DATABASE_URL`: Optional. Postgres connection string. If not set, uses SQLite 28 + - `INITIAL_LINKS`: Optional. Semicolon-separated list of initial links in format "url,code;url2,code2" 29 + - `SERVER_HOST`: Optional. Default: "127.0.0.1" 30 + - `SERVER_PORT`: Optional. Default: "8080" 31 + 32 + If `SIMPLELINK_USER` and `SIMPLELINK_PASS` are not passed, an admin-setup-token is pasted to the console and as a text file in the project root. 33 + 34 + ### From Docker Compose 35 + 36 + Edit the docker-compose.yml file. It comes included with a PostgreSQL db configuration. 37 + 38 + ## Build 39 + 40 + ### From Source 41 + 42 + First configure .env.example and save it to .env 43 + 44 + ```bash 45 + git clone https://github.com/waveringana/simplelink && cd simplelink 46 + ./build.sh 47 + cargo run 48 + ``` 49 + 50 + Alternatively for a binary build: 51 + 52 + ```bash 53 + ./build.sh --binary 54 + ``` 55 + 56 + then check /target/release for the binary named `SimpleGit` 57 + 58 + ### From Docker 59 + 60 + ```bash 61 + docker build -t simplelink . 62 + docker run -p 8080:8080 \ 63 + -e JWT_SECRET=change-me-in-production \ 64 + -e SIMPLELINK_USER=admin@example.com \ 65 + -e SIMPLELINK_PASS=your-secure-password \ 66 + -v simplelink_data:/data \ 67 + simplelink 68 + ``` 69 + 70 + ### From Docker Compose 71 + 72 + Adjust the included docker-compose.yml to your liking; it includes a postgres config as well. 73 + 74 + ## Features 75 + 76 + - Support for both PostgreSQL and SQLite databases 77 + - Initial links can be configured via environment variables 78 + - Admin user can be created on first run via environment variables 79 + - Link click tracking and statistics 80 + - Lightweight and performant
-1
admin-setup-token.txt
··· 1 - fqfO6awRz3mkc2Kxunkp1uTQcXaSfGD9
+16 -14
build.sh
··· 1 1 #!/bin/bash 2 2 3 3 # Default values 4 - API_URL="http://localhost:8080" 4 + #API_URL="http://localhost:8080" 5 5 RELEASE_MODE=false 6 + BINARY_MODE=false 6 7 7 8 # Parse command line arguments 8 9 for arg in "$@" 9 10 do 10 11 case $arg in 11 - api-domain=*) 12 - API_URL="${arg#*=}" 12 + #api-domain=*) 13 + #API_URL="${arg#*=}" 14 + #shift 15 + #;; 16 + --release) 17 + RELEASE_MODE=true 13 18 shift 14 19 ;; 15 - --release) 16 - RELEASE_MODE=true 20 + --binary) 21 + BINARY_MODE=true 17 22 shift 18 23 ;; 19 24 esac 20 25 done 21 26 22 - echo "Building project with API_URL: $API_URL" 27 + #echo "Building project with API_URL: $API_URL" 23 28 echo "Release mode: $RELEASE_MODE" 24 29 25 30 # Check if cargo is installed ··· 37 42 # Build frontend 38 43 echo "Building frontend..." 39 44 # Create .env file for Vite 40 - echo "VITE_API_URL=$API_URL" > frontend/.env 45 + #echo "VITE_API_URL=$API_URL" > frontend/.env 41 46 42 47 # Install frontend dependencies and build 43 48 cd frontend ··· 45 50 npm run build 46 51 cd .. 47 52 48 - # Create static directory if it doesn't exist 53 + # Create static directory and copy frontend build 49 54 mkdir -p static 50 - 51 - # Clean existing static files 52 55 rm -rf static/* 53 - 54 - # Copy built files to static directory 55 56 cp -r frontend/dist/* static/ 56 57 57 58 # Build Rust project ··· 62 63 # Create release directory 63 64 mkdir -p release 64 65 65 - # Copy binary and static files to release directory 66 + # Copy only the binary to release directory 66 67 cp target/release/simplelink release/ 67 - cp -r static release/ 68 68 cp .env.example release/.env 69 69 70 70 # Create a tar archive 71 71 tar -czf release.tar.gz release/ 72 72 73 73 echo "Release archive created: release.tar.gz" 74 + elif [ "$BINARY_MODE" = true ]; then 75 + cargo build --release 74 76 else 75 77 cargo build 76 78 fi
+4 -7
docker-compose.yml
··· 19 19 - shortener-network 20 20 21 21 app: 22 - build: 23 - context: . 24 - dockerfile: Dockerfile 25 - args: 26 - - API_URL=${API_URL:-http://localhost:3000} 22 + image: ghcr.io/waveringana/simplelink:v2.2 27 23 container_name: shortener-app 28 24 ports: 29 - - "3000:3000" 25 + - "8080:8080" 30 26 environment: 31 27 - DATABASE_URL=postgresql://shortener:shortener123@db:5432/shortener 32 28 - SERVER_HOST=0.0.0.0 33 - - SERVER_PORT=3000 29 + - SERVER_PORT=8080 30 + - JWT_SECRET=change-me-in-production 34 31 depends_on: 35 32 db: 36 33 condition: service_healthy
-858
frontend/bun.lock
··· 1 - { 2 - "lockfileVersion": 1, 3 - "workspaces": { 4 - "": { 5 - "name": "frontend", 6 - "dependencies": { 7 - "@emotion/react": "^11.14.0", 8 - "@hookform/resolvers": "^3.10.0", 9 - "@icons-pack/react-simple-icons": "^11.2.0", 10 - "@mantine/core": "^7.16.1", 11 - "@mantine/form": "^7.16.1", 12 - "@mantine/hooks": "^7.16.1", 13 - "@radix-ui/react-dialog": "^1.1.5", 14 - "@radix-ui/react-dropdown-menu": "^2.1.5", 15 - "@radix-ui/react-label": "^2.1.1", 16 - "@radix-ui/react-slot": "^1.1.1", 17 - "@radix-ui/react-tabs": "^1.1.2", 18 - "@radix-ui/react-toast": "^1.2.5", 19 - "@tailwindcss/vite": "^4.0.0", 20 - "axios": "^1.7.9", 21 - "class-variance-authority": "^0.7.1", 22 - "clsx": "^2.1.1", 23 - "lucide-react": "^0.474.0", 24 - "react": "^18.3.1", 25 - "react-dom": "^18.3.1", 26 - "react-hook-form": "^7.54.2", 27 - "recharts": "^2.15.0", 28 - "tailwind-merge": "^2.6.0", 29 - "tailwindcss-animate": "^1.0.7", 30 - "zod": "^3.24.1", 31 - }, 32 - "devDependencies": { 33 - "@eslint/js": "^9.17.0", 34 - "@tailwindcss/postcss": "^4.0.0", 35 - "@types/node": "^22.10.10", 36 - "@types/react": "^18.3.18", 37 - "@types/react-dom": "^18.3.5", 38 - "@vitejs/plugin-react": "^4.3.4", 39 - "eslint": "^9.17.0", 40 - "eslint-plugin-react-hooks": "^5.0.0", 41 - "eslint-plugin-react-refresh": "^0.4.16", 42 - "globals": "^15.14.0", 43 - "postcss": "^8.5.1", 44 - "tailwindcss": "^4.0.0", 45 - "typescript": "~5.6.2", 46 - "typescript-eslint": "^8.18.2", 47 - "vite": "^6.0.5", 48 - }, 49 - }, 50 - }, 51 - "packages": { 52 - "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], 53 - 54 - "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="], 55 - 56 - "@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="], 57 - 58 - "@babel/compat-data": ["@babel/compat-data@7.26.5", "", {}, "sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg=="], 59 - 60 - "@babel/core": ["@babel/core@7.26.7", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", "@babel/generator": "^7.26.5", "@babel/helper-compilation-targets": "^7.26.5", "@babel/helper-module-transforms": "^7.26.0", "@babel/helpers": "^7.26.7", "@babel/parser": "^7.26.7", "@babel/template": "^7.25.9", "@babel/traverse": "^7.26.7", "@babel/types": "^7.26.7", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA=="], 61 - 62 - "@babel/generator": ["@babel/generator@7.26.5", "", { "dependencies": { "@babel/parser": "^7.26.5", "@babel/types": "^7.26.5", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw=="], 63 - 64 - "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.26.5", "", { "dependencies": { "@babel/compat-data": "^7.26.5", "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA=="], 65 - 66 - "@babel/helper-module-imports": ["@babel/helper-module-imports@7.25.9", "", { "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw=="], 67 - 68 - "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.26.0", "", { "dependencies": { "@babel/helper-module-imports": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9", "@babel/traverse": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw=="], 69 - 70 - "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.26.5", "", {}, "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg=="], 71 - 72 - "@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.9", "", {}, "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA=="], 73 - 74 - "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="], 75 - 76 - "@babel/helper-validator-option": ["@babel/helper-validator-option@7.25.9", "", {}, "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw=="], 77 - 78 - "@babel/helpers": ["@babel/helpers@7.26.7", "", { "dependencies": { "@babel/template": "^7.25.9", "@babel/types": "^7.26.7" } }, "sha512-8NHiL98vsi0mbPQmYAGWwfcFaOy4j2HY49fXJCfuDcdE7fMIsH9a7GdaeXpIBsbT7307WU8KCMp5pUVDNL4f9A=="], 79 - 80 - "@babel/parser": ["@babel/parser@7.26.7", "", { "dependencies": { "@babel/types": "^7.26.7" }, "bin": "./bin/babel-parser.js" }, "sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w=="], 81 - 82 - "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg=="], 83 - 84 - "@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg=="], 85 - 86 - "@babel/runtime": ["@babel/runtime@7.26.7", "", { "dependencies": { "regenerator-runtime": "^0.14.0" } }, "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ=="], 87 - 88 - "@babel/template": ["@babel/template@7.25.9", "", { "dependencies": { "@babel/code-frame": "^7.25.9", "@babel/parser": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg=="], 89 - 90 - "@babel/traverse": ["@babel/traverse@7.26.7", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/generator": "^7.26.5", "@babel/parser": "^7.26.7", "@babel/template": "^7.25.9", "@babel/types": "^7.26.7", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA=="], 91 - 92 - "@babel/types": ["@babel/types@7.26.7", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" } }, "sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg=="], 93 - 94 - "@emotion/babel-plugin": ["@emotion/babel-plugin@11.13.5", "", { "dependencies": { "@babel/helper-module-imports": "^7.16.7", "@babel/runtime": "^7.18.3", "@emotion/hash": "^0.9.2", "@emotion/memoize": "^0.9.0", "@emotion/serialize": "^1.3.3", "babel-plugin-macros": "^3.1.0", "convert-source-map": "^1.5.0", "escape-string-regexp": "^4.0.0", "find-root": "^1.1.0", "source-map": "^0.5.7", "stylis": "4.2.0" } }, "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ=="], 95 - 96 - "@emotion/cache": ["@emotion/cache@11.14.0", "", { "dependencies": { "@emotion/memoize": "^0.9.0", "@emotion/sheet": "^1.4.0", "@emotion/utils": "^1.4.2", "@emotion/weak-memoize": "^0.4.0", "stylis": "4.2.0" } }, "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA=="], 97 - 98 - "@emotion/hash": ["@emotion/hash@0.9.2", "", {}, "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g=="], 99 - 100 - "@emotion/memoize": ["@emotion/memoize@0.9.0", "", {}, "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ=="], 101 - 102 - "@emotion/react": ["@emotion/react@11.14.0", "", { "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", "@emotion/cache": "^11.14.0", "@emotion/serialize": "^1.3.3", "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", "@emotion/utils": "^1.4.2", "@emotion/weak-memoize": "^0.4.0", "hoist-non-react-statics": "^3.3.1" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA=="], 103 - 104 - "@emotion/serialize": ["@emotion/serialize@1.3.3", "", { "dependencies": { "@emotion/hash": "^0.9.2", "@emotion/memoize": "^0.9.0", "@emotion/unitless": "^0.10.0", "@emotion/utils": "^1.4.2", "csstype": "^3.0.2" } }, "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA=="], 105 - 106 - "@emotion/sheet": ["@emotion/sheet@1.4.0", "", {}, "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg=="], 107 - 108 - "@emotion/unitless": ["@emotion/unitless@0.10.0", "", {}, "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg=="], 109 - 110 - "@emotion/use-insertion-effect-with-fallbacks": ["@emotion/use-insertion-effect-with-fallbacks@1.2.0", "", { "peerDependencies": { "react": ">=16.8.0" } }, "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg=="], 111 - 112 - "@emotion/utils": ["@emotion/utils@1.4.2", "", {}, "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA=="], 113 - 114 - "@emotion/weak-memoize": ["@emotion/weak-memoize@0.4.0", "", {}, "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg=="], 115 - 116 - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.24.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA=="], 117 - 118 - "@esbuild/android-arm": ["@esbuild/android-arm@0.24.2", "", { "os": "android", "cpu": "arm" }, "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q=="], 119 - 120 - "@esbuild/android-arm64": ["@esbuild/android-arm64@0.24.2", "", { "os": "android", "cpu": "arm64" }, "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg=="], 121 - 122 - "@esbuild/android-x64": ["@esbuild/android-x64@0.24.2", "", { "os": "android", "cpu": "x64" }, "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw=="], 123 - 124 - "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.24.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA=="], 125 - 126 - "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.24.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA=="], 127 - 128 - "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.24.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg=="], 129 - 130 - "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.24.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q=="], 131 - 132 - "@esbuild/linux-arm": ["@esbuild/linux-arm@0.24.2", "", { "os": "linux", "cpu": "arm" }, "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA=="], 133 - 134 - "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.24.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg=="], 135 - 136 - "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.24.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw=="], 137 - 138 - "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ=="], 139 - 140 - "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw=="], 141 - 142 - "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.24.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw=="], 143 - 144 - "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q=="], 145 - 146 - "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.24.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw=="], 147 - 148 - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.24.2", "", { "os": "linux", "cpu": "x64" }, "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q=="], 149 - 150 - "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.24.2", "", { "os": "none", "cpu": "arm64" }, "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw=="], 151 - 152 - "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.24.2", "", { "os": "none", "cpu": "x64" }, "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw=="], 153 - 154 - "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.24.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A=="], 155 - 156 - "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.24.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA=="], 157 - 158 - "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.24.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig=="], 159 - 160 - "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.24.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ=="], 161 - 162 - "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.24.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA=="], 163 - 164 - "@esbuild/win32-x64": ["@esbuild/win32-x64@0.24.2", "", { "os": "win32", "cpu": "x64" }, "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg=="], 165 - 166 - "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.4.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA=="], 167 - 168 - "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="], 169 - 170 - "@eslint/config-array": ["@eslint/config-array@0.19.1", "", { "dependencies": { "@eslint/object-schema": "^2.1.5", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA=="], 171 - 172 - "@eslint/core": ["@eslint/core@0.10.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw=="], 173 - 174 - "@eslint/eslintrc": ["@eslint/eslintrc@3.2.0", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w=="], 175 - 176 - "@eslint/js": ["@eslint/js@9.19.0", "", {}, "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ=="], 177 - 178 - "@eslint/object-schema": ["@eslint/object-schema@2.1.5", "", {}, "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ=="], 179 - 180 - "@eslint/plugin-kit": ["@eslint/plugin-kit@0.2.5", "", { "dependencies": { "@eslint/core": "^0.10.0", "levn": "^0.4.1" } }, "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A=="], 181 - 182 - "@floating-ui/core": ["@floating-ui/core@1.6.9", "", { "dependencies": { "@floating-ui/utils": "^0.2.9" } }, "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw=="], 183 - 184 - "@floating-ui/dom": ["@floating-ui/dom@1.6.13", "", { "dependencies": { "@floating-ui/core": "^1.6.0", "@floating-ui/utils": "^0.2.9" } }, "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w=="], 185 - 186 - "@floating-ui/react": ["@floating-ui/react@0.26.28", "", { "dependencies": { "@floating-ui/react-dom": "^2.1.2", "@floating-ui/utils": "^0.2.8", "tabbable": "^6.0.0" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw=="], 187 - 188 - "@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.2", "", { "dependencies": { "@floating-ui/dom": "^1.0.0" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A=="], 189 - 190 - "@floating-ui/utils": ["@floating-ui/utils@0.2.9", "", {}, "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg=="], 191 - 192 - "@hookform/resolvers": ["@hookform/resolvers@3.10.0", "", { "peerDependencies": { "react-hook-form": "^7.0.0" } }, "sha512-79Dv+3mDF7i+2ajj7SkypSKHhl1cbln1OGavqrsF7p6mbUv11xpqpacPsGDCTRvCSjEEIez2ef1NveSVL3b0Ag=="], 193 - 194 - "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], 195 - 196 - "@humanfs/node": ["@humanfs/node@0.16.6", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" } }, "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw=="], 197 - 198 - "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], 199 - 200 - "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.1", "", {}, "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA=="], 201 - 202 - "@icons-pack/react-simple-icons": ["@icons-pack/react-simple-icons@11.2.0", "", { "peerDependencies": { "react": "^16.13 || ^17 || ^18 || ^19" } }, "sha512-jCJ+1Fe0yiBQGYSfhx8QGU/9o27t8J4Hw3mxHEI9vohRltLSi5CaPzO2fCQcMNeTrAUAm4j+yaDuAutskiKRjA=="], 203 - 204 - "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="], 205 - 206 - "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], 207 - 208 - "@jridgewell/set-array": ["@jridgewell/set-array@1.2.1", "", {}, "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="], 209 - 210 - "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], 211 - 212 - "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="], 213 - 214 - "@mantine/core": ["@mantine/core@7.16.1", "", { "dependencies": { "@floating-ui/react": "^0.26.28", "clsx": "^2.1.1", "react-number-format": "^5.4.3", "react-remove-scroll": "^2.6.2", "react-textarea-autosize": "8.5.6", "type-fest": "^4.27.0" }, "peerDependencies": { "@mantine/hooks": "7.16.1", "react": "^18.x || ^19.x", "react-dom": "^18.x || ^19.x" } }, "sha512-HYdjCeMU3dUJbc1CrAAedeAASTG5kVyL/qsiuYh5b7BoG0qsRtK8WJxBpUjW6VqtJpUaE94c5tlBJ8MgAmPHTQ=="], 215 - 216 - "@mantine/form": ["@mantine/form@7.16.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "klona": "^2.0.6" }, "peerDependencies": { "react": "^18.x || ^19.x" } }, "sha512-SZfOlmO14oAYdqo3SJKJlPrSNaeWyTPIPV/cur/4sPf114cAyggEZHoHJEjy2yA8UccfwYZx39yWrwxQCb8J8w=="], 217 - 218 - "@mantine/hooks": ["@mantine/hooks@7.16.1", "", { "peerDependencies": { "react": "^18.x || ^19.x" } }, "sha512-+hER8E4d2ByfQ/DKIXGM3Euxb7IH5ArSjzzzoF21sG095iXIryOCob22ZanrmiXCoAzKKdxqgVj4Di67ikLYSQ=="], 219 - 220 - "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], 221 - 222 - "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], 223 - 224 - "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], 225 - 226 - "@radix-ui/primitive": ["@radix-ui/primitive@1.1.1", "", {}, "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA=="], 227 - 228 - "@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.1", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-NaVpZfmv8SKeZbn4ijN2V3jlHA9ngBG16VnIIm22nUR0Yk8KUALyBxT3KYEUnNuch9sTE8UTsS3whzBgKOL30w=="], 229 - 230 - "@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.1", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-primitive": "2.0.1", "@radix-ui/react-slot": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-LwT3pSho9Dljg+wY2KN2mrrh6y3qELfftINERIzBUO9e0N+t0oMTyn3k9iv+ZqgrwGkRnLpNJrsMv9BZlt2yuA=="], 231 - 232 - "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw=="], 233 - 234 - "@radix-ui/react-context": ["@radix-ui/react-context@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q=="], 235 - 236 - "@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.5", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.4", "@radix-ui/react-focus-guards": "1.1.1", "@radix-ui/react-focus-scope": "1.1.1", "@radix-ui/react-id": "1.1.0", "@radix-ui/react-portal": "1.1.3", "@radix-ui/react-presence": "1.1.2", "@radix-ui/react-primitive": "2.0.1", "@radix-ui/react-slot": "1.1.1", "@radix-ui/react-use-controllable-state": "1.1.0", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-LaO3e5h/NOEL4OfXjxD43k9Dx+vn+8n+PCFt6uhX/BADFflllyv3WJG6rgvvSVBxpTch938Qq/LGc2MMxipXPw=="], 237 - 238 - "@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg=="], 239 - 240 - "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.4", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-primitive": "2.0.1", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-escape-keydown": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-XDUI0IVYVSwjMXxM6P4Dfti7AH+Y4oS/TB+sglZ/EXc7cqLwGAmp1NlMrcUjj7ks6R5WTZuWKv44FBbLpwU3sA=="], 241 - 242 - "@radix-ui/react-dropdown-menu": ["@radix-ui/react-dropdown-menu@2.1.5", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-id": "1.1.0", "@radix-ui/react-menu": "2.1.5", "@radix-ui/react-primitive": "2.0.1", "@radix-ui/react-use-controllable-state": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-50ZmEFL1kOuLalPKHrLWvPFMons2fGx9TqQCWlPwDVpbAnaUJ1g4XNcKqFNMQymYU0kKWR4MDDi+9vUQBGFgcQ=="], 243 - 244 - "@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg=="], 245 - 246 - "@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.1", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-primitive": "2.0.1", "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-01omzJAYRxXdG2/he/+xy+c8a8gCydoQ1yOxnWNcRhrrBW5W+RQJ22EK1SaO8tb3WoUsuEw7mJjBozPzihDFjA=="], 247 - 248 - "@radix-ui/react-id": ["@radix-ui/react-id@1.1.0", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA=="], 249 - 250 - "@radix-ui/react-label": ["@radix-ui/react-label@2.1.1", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-UUw5E4e/2+4kFMH7+YxORXGWggtY6sM8WIwh5RZchhLuUg2H1hc98Py+pr8HMz6rdaYrK2t296ZEjYLOCO5uUw=="], 251 - 252 - "@radix-ui/react-menu": ["@radix-ui/react-menu@2.1.5", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-collection": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-direction": "1.1.0", "@radix-ui/react-dismissable-layer": "1.1.4", "@radix-ui/react-focus-guards": "1.1.1", "@radix-ui/react-focus-scope": "1.1.1", "@radix-ui/react-id": "1.1.0", "@radix-ui/react-popper": "1.2.1", "@radix-ui/react-portal": "1.1.3", "@radix-ui/react-presence": "1.1.2", "@radix-ui/react-primitive": "2.0.1", "@radix-ui/react-roving-focus": "1.1.1", "@radix-ui/react-slot": "1.1.1", "@radix-ui/react-use-callback-ref": "1.1.0", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-uH+3w5heoMJtqVCgYOtYVMECk1TOrkUn0OG0p5MqXC0W2ppcuVeESbou8PTHoqAjbdTEK19AGXBWcEtR5WpEQg=="], 253 - 254 - "@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.1", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-primitive": "2.0.1", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-layout-effect": "1.1.0", "@radix-ui/react-use-rect": "1.1.0", "@radix-ui/react-use-size": "1.1.0", "@radix-ui/rect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-3kn5Me69L+jv82EKRuQCXdYyf1DqHwD2U/sxoNgBGCB7K9TRc3bQamQ+5EPM9EvyPdli0W41sROd+ZU1dTCztw=="], 255 - 256 - "@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.3", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.1", "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-NciRqhXnGojhT93RPyDaMPfLH3ZSl4jjIFbZQ1b/vxvZEdHsBZ49wP9w8L3HzUQwep01LcWtkUvm0OVB5JAHTw=="], 257 - 258 - "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg=="], 259 - 260 - "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.1", "", { "dependencies": { "@radix-ui/react-slot": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg=="], 261 - 262 - "@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.1", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-collection": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-direction": "1.1.0", "@radix-ui/react-id": "1.1.0", "@radix-ui/react-primitive": "2.0.1", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-controllable-state": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-QE1RoxPGJ/Nm8Qmk0PxP8ojmoaS67i0s7hVssS7KuI2FQoc/uzVlZsqKfQvxPE6D8hICCPHJ4D88zNhT3OOmkw=="], 263 - 264 - "@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.1", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g=="], 265 - 266 - "@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.2", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-direction": "1.1.0", "@radix-ui/react-id": "1.1.0", "@radix-ui/react-presence": "1.1.2", "@radix-ui/react-primitive": "2.0.1", "@radix-ui/react-roving-focus": "1.1.1", "@radix-ui/react-use-controllable-state": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9u/tQJMcC2aGq7KXpGivMm1mgq7oRJKXphDwdypPd/j21j/2znamPU8WkXgnhUaTrSFNIt8XhOyCAupg8/GbwQ=="], 267 - 268 - "@radix-ui/react-toast": ["@radix-ui/react-toast@1.2.5", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-collection": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.4", "@radix-ui/react-portal": "1.1.3", "@radix-ui/react-presence": "1.1.2", "@radix-ui/react-primitive": "2.0.1", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-controllable-state": "1.1.0", "@radix-ui/react-use-layout-effect": "1.1.0", "@radix-ui/react-visually-hidden": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-ZzUsAaOx8NdXZZKcFNDhbSlbsCUy8qQWmzTdgrlrhhZAOx2ofLtKrBDW9fkqhFvXgmtv560Uj16pkLkqML7SHA=="], 269 - 270 - "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], 271 - 272 - "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.1.0", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw=="], 273 - 274 - "@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.0", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw=="], 275 - 276 - "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], 277 - 278 - "@radix-ui/react-use-rect": ["@radix-ui/react-use-rect@1.1.0", "", { "dependencies": { "@radix-ui/rect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ=="], 279 - 280 - "@radix-ui/react-use-size": ["@radix-ui/react-use-size@1.1.0", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw=="], 281 - 282 - "@radix-ui/react-visually-hidden": ["@radix-ui/react-visually-hidden@1.1.1", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-vVfA2IZ9q/J+gEamvj761Oq1FpWgCDaNOOIfbPVp2MVPLEomUr5+Vf7kJGwQ24YxZSlQVar7Bes8kyTo5Dshpg=="], 283 - 284 - "@radix-ui/rect": ["@radix-ui/rect@1.1.0", "", {}, "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg=="], 285 - 286 - "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.32.0", "", { "os": "android", "cpu": "arm" }, "sha512-G2fUQQANtBPsNwiVFg4zKiPQyjVKZCUdQUol53R8E71J7AsheRMV/Yv/nB8giOcOVqP7//eB5xPqieBYZe9bGg=="], 287 - 288 - "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-qhFwQ+ljoymC+j5lXRv8DlaJYY/+8vyvYmVx074zrLsu5ZGWYsJNLjPPVJJjhZQpyAKUGPydOq9hRLLNvh1s3A=="], 289 - 290 - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-44n/X3lAlWsEY6vF8CzgCx+LQaoqWGN7TzUfbJDiTIOjJm4+L2Yq+r5a8ytQRGyPqgJDs3Rgyo8eVL7n9iW6AQ=="], 291 - 292 - "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-F9ct0+ZX5Np6+ZDztxiGCIvlCaW87HBdHcozUfsHnj1WCUTBUubAoanhHUfnUHZABlElyRikI0mgcw/qdEm2VQ=="], 293 - 294 - "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.32.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-JpsGxLBB2EFXBsTLHfkZDsXSpSmKD3VxXCgBQtlPcuAqB8TlqtLcbeMhxXQkCDv1avgwNjF8uEIbq5p+Cee0PA=="], 295 - 296 - "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.32.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-wegiyBT6rawdpvnD9lmbOpx5Sph+yVZKHbhnSP9MqUEDX08G4UzMU+D87jrazGE7lRSyTRs6NEYHtzfkJ3FjjQ=="], 297 - 298 - "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-3pA7xecItbgOs1A5H58dDvOUEboG5UfpTq3WzAdF54acBbUM+olDJAPkgj1GRJ4ZqE12DZ9/hNS2QZk166v92A=="], 299 - 300 - "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-Y7XUZEVISGyge51QbYyYAEHwpGgmRrAxQXO3siyYo2kmaj72USSG8LtlQQgAtlGfxYiOwu+2BdbPjzEpcOpRmQ=="], 301 - 302 - "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-r7/OTF5MqeBrZo5omPXcTnjvv1GsrdH8a8RerARvDFiDwFpDVDnJyByYM/nX+mvks8XXsgPUxkwe/ltaX2VH7w=="], 303 - 304 - "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-HJbifC9vex9NqnlodV2BHVFNuzKL5OnsV2dvTw6e1dpZKkNjPG6WUq+nhEYV6Hv2Bv++BXkwcyoGlXnPrjAKXw=="], 305 - 306 - "@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.32.0", "", { "os": "linux", "cpu": "none" }, "sha512-VAEzZTD63YglFlWwRj3taofmkV1V3xhebDXffon7msNz4b14xKsz7utO6F8F4cqt8K/ktTl9rm88yryvDpsfOw=="], 307 - 308 - "@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.32.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-Sts5DST1jXAc9YH/iik1C9QRsLcCoOScf3dfbY5i4kH9RJpKxiTBXqm7qU5O6zTXBTEZry69bGszr3SMgYmMcQ=="], 309 - 310 - "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.32.0", "", { "os": "linux", "cpu": "none" }, "sha512-qhlXeV9AqxIyY9/R1h1hBD6eMvQCO34ZmdYvry/K+/MBs6d1nRFLm6BOiITLVI+nFAAB9kUB6sdJRKyVHXnqZw=="], 311 - 312 - "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.32.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-8ZGN7ExnV0qjXa155Rsfi6H8M4iBBwNLBM9lcVS+4NcSzOFaNqmt7djlox8pN1lWrRPMRRQ8NeDlozIGx3Omsw=="], 313 - 314 - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-VDzNHtLLI5s7xd/VubyS10mq6TxvZBp+4NRWoW+Hi3tgV05RtVm4qK99+dClwTN1McA6PHwob6DEJ6PlXbY83A=="], 315 - 316 - "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-qcb9qYDlkxz9DxJo7SDhWxTWV1gFuwznjbTiov289pASxlfGbaOD54mgbs9+z94VwrXtKTu+2RqwlSTbiOqxGg=="], 317 - 318 - "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.32.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-pFDdotFDMXW2AXVbfdUEfidPAk/OtwE/Hd4eYMTNVVaCQ6Yl8et0meDaKNL63L44Haxv4UExpv9ydSf3aSayDg=="], 319 - 320 - "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.32.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-/TG7WfrCAjeRNDvI4+0AAMoHxea/USWhAzf9PVDFHbcqrQ7hMMKp4jZIy4VEjk72AAfN5k4TiSMRXRKf/0akSw=="], 321 - 322 - "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-5hqO5S3PTEO2E5VjCePxv40gIgyS2KvO7E7/vvC/NbIW4SIRamkMr1hqj+5Y67fbBWv/bQLB6KelBQmXlyCjWA=="], 323 - 324 - "@tailwindcss/node": ["@tailwindcss/node@4.0.0", "", { "dependencies": { "enhanced-resolve": "^5.18.0", "jiti": "^2.4.2", "tailwindcss": "4.0.0" } }, "sha512-tfG2uBvo6j6kDIPmntxwXggCOZAt7SkpAXJ6pTIYirNdk5FBqh/CZZ9BZPpgcl/tNFLs6zc4yghM76sqiELG9g=="], 325 - 326 - "@tailwindcss/oxide": ["@tailwindcss/oxide@4.0.0", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.0.0", "@tailwindcss/oxide-darwin-arm64": "4.0.0", "@tailwindcss/oxide-darwin-x64": "4.0.0", "@tailwindcss/oxide-freebsd-x64": "4.0.0", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.0.0", "@tailwindcss/oxide-linux-arm64-gnu": "4.0.0", "@tailwindcss/oxide-linux-arm64-musl": "4.0.0", "@tailwindcss/oxide-linux-x64-gnu": "4.0.0", "@tailwindcss/oxide-linux-x64-musl": "4.0.0", "@tailwindcss/oxide-win32-arm64-msvc": "4.0.0", "@tailwindcss/oxide-win32-x64-msvc": "4.0.0" } }, "sha512-W3FjpJgy4VV1JiL7iBYDf2n/WkeDg1Il+0Q7eWnqPyvkPPCo/Mbwc5BiaT7dfBNV6tQKAhVE34rU5xl8pSl50w=="], 327 - 328 - "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.0.0", "", { "os": "android", "cpu": "arm64" }, "sha512-EAhjU0+FIdyGPR+7MbBWubLLPtmOu+p7c2egTTFBRk/n//zYjNvVK0WhcBK5Y7oUB5mo4EjA2mCbY7dcEMWSRw=="], 329 - 330 - "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.0.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-hdz4xnSWS11cIp+7ye+3dGHqs0X33z+BXXTtgPOguDWVa+TdXUzwxonklSzf5wlJFuot3dv5eWzhlNai0oYYQg=="], 331 - 332 - "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.0.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-+dOUUaXTkPKKhtUI9QtVaYg+MpmLh2CN0dHohiYXaBirEyPMkjaT0zbRgzQlNnQWjCVVXPQluIEb0OMEjSTH+Q=="], 333 - 334 - "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.0.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-CJhGDhxnrmu4SwyC62fA+wP24MhA/TZlIhRHqg1kRuIHoGoVR2uSSm1qxTxU37tSSZj8Up0q6jsBJCAP4k7rgQ=="], 335 - 336 - "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.0.0", "", { "os": "linux", "cpu": "arm" }, "sha512-Wy7Av0xzXfY2ujZBcYy4+7GQm25/J1iHvlQU2CfwdDCuPWfIjYzR6kggz+uVdSJyKV2s64znchBxRE8kV4uXSA=="], 337 - 338 - "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.0.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-srwBo2l6pvM0swBntc1ucuhGsfFOLkqPRFQ3dWARRTfSkL1U9nAsob2MKc/n47Eva/W9pZZgMOuf7rDw8pK1Ew=="], 339 - 340 - "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.0.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-abhusswkduYWuezkBmgo0K0/erGq3M4Se5xP0fhc/0dKs0X/rJUYYCFWntHb3IGh3aVzdQ0SXJs93P76DbUqtw=="], 341 - 342 - "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.0.0", "", { "os": "linux", "cpu": "x64" }, "sha512-hGtRYIUEx377/HlU49+jvVKKwU1MDSKYSMMs0JFO2Wp7LGxk5+0j5+RBk9NFnmp/lbp32yPTgIOO5m1BmDq36A=="], 343 - 344 - "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.0.0", "", { "os": "linux", "cpu": "x64" }, "sha512-7xgQgSAThs0I14VAgmxpJnK6XFSZBxHMGoDXkLyYkEnu+8WRQMbCP93dkCUn2PIv+Q+JulRgc00PJ09uORSLXQ=="], 345 - 346 - "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.0.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-qEcgTIPcWY5ZE7f6VxQ/JPrSFMcehzVIlZj7sGE3mVd5YWreAT+Fl1vSP8q2pjnWXn0avZG3Iw7a2hJQAm+fTQ=="], 347 - 348 - "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.0.0", "", { "os": "win32", "cpu": "x64" }, "sha512-bqT0AY8RXb8GMDy28JtngvqaOSB2YixbLPLvUo6I6lkvvUwA6Eqh2Tj60e2Lh7O/k083f8tYiB0WEK4wmTI7Jg=="], 349 - 350 - "@tailwindcss/postcss": ["@tailwindcss/postcss@4.0.0", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "^4.0.0", "@tailwindcss/oxide": "^4.0.0", "lightningcss": "^1.29.1", "postcss": "^8.4.41", "tailwindcss": "4.0.0" } }, "sha512-lI2bPk4TvwavHdehjr5WiC6HnZ59hacM6ySEo4RM/H7tsjWd8JpqiNW9ThH7rO/yKtrn4mGBoXshpvn8clXjPg=="], 351 - 352 - "@tailwindcss/vite": ["@tailwindcss/vite@4.0.0", "", { "dependencies": { "@tailwindcss/node": "^4.0.0", "@tailwindcss/oxide": "^4.0.0", "lightningcss": "^1.29.1", "tailwindcss": "4.0.0" }, "peerDependencies": { "vite": "^5.2.0 || ^6" } }, "sha512-4uukMiU9gHui8KMPMdWic5SP1O/tmQ1NFSRNrQWmcop5evAVl/LZ6/LuWL3quEiecp2RBcRWwqJrG+mFXlRlew=="], 353 - 354 - "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="], 355 - 356 - "@types/babel__generator": ["@types/babel__generator@7.6.8", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw=="], 357 - 358 - "@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="], 359 - 360 - "@types/babel__traverse": ["@types/babel__traverse@7.20.6", "", { "dependencies": { "@babel/types": "^7.20.7" } }, "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg=="], 361 - 362 - "@types/d3-array": ["@types/d3-array@3.2.1", "", {}, "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg=="], 363 - 364 - "@types/d3-color": ["@types/d3-color@3.1.3", "", {}, "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A=="], 365 - 366 - "@types/d3-ease": ["@types/d3-ease@3.0.2", "", {}, "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA=="], 367 - 368 - "@types/d3-interpolate": ["@types/d3-interpolate@3.0.4", "", { "dependencies": { "@types/d3-color": "*" } }, "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA=="], 369 - 370 - "@types/d3-path": ["@types/d3-path@3.1.0", "", {}, "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ=="], 371 - 372 - "@types/d3-scale": ["@types/d3-scale@4.0.8", "", { "dependencies": { "@types/d3-time": "*" } }, "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ=="], 373 - 374 - "@types/d3-shape": ["@types/d3-shape@3.1.7", "", { "dependencies": { "@types/d3-path": "*" } }, "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg=="], 375 - 376 - "@types/d3-time": ["@types/d3-time@3.0.4", "", {}, "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g=="], 377 - 378 - "@types/d3-timer": ["@types/d3-timer@3.0.2", "", {}, "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw=="], 379 - 380 - "@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="], 381 - 382 - "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], 383 - 384 - "@types/node": ["@types/node@22.10.10", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-X47y/mPNzxviAGY5TcYPtYL8JsY3kAq2n8fMmKoRCxq/c4v4pyGNCzM2R6+M5/umG4ZfHuT+sgqDYqWc9rJ6ww=="], 385 - 386 - "@types/parse-json": ["@types/parse-json@4.0.2", "", {}, "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="], 387 - 388 - "@types/prop-types": ["@types/prop-types@15.7.14", "", {}, "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ=="], 389 - 390 - "@types/react": ["@types/react@18.3.18", "", { "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" } }, "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ=="], 391 - 392 - "@types/react-dom": ["@types/react-dom@18.3.5", "", { "peerDependencies": { "@types/react": "^18.0.0" } }, "sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q=="], 393 - 394 - "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.21.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.21.0", "@typescript-eslint/type-utils": "8.21.0", "@typescript-eslint/utils": "8.21.0", "@typescript-eslint/visitor-keys": "8.21.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^2.0.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-eTH+UOR4I7WbdQnG4Z48ebIA6Bgi7WO8HvFEneeYBxG8qCOYgTOFPSg6ek9ITIDvGjDQzWHcoWHCDO2biByNzA=="], 395 - 396 - "@typescript-eslint/parser": ["@typescript-eslint/parser@8.21.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.21.0", "@typescript-eslint/types": "8.21.0", "@typescript-eslint/typescript-estree": "8.21.0", "@typescript-eslint/visitor-keys": "8.21.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-Wy+/sdEH9kI3w9civgACwabHbKl+qIOu0uFZ9IMKzX3Jpv9og0ZBJrZExGrPpFAY7rWsXuxs5e7CPPP17A4eYA=="], 397 - 398 - "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.21.0", "", { "dependencies": { "@typescript-eslint/types": "8.21.0", "@typescript-eslint/visitor-keys": "8.21.0" } }, "sha512-G3IBKz0/0IPfdeGRMbp+4rbjfSSdnGkXsM/pFZA8zM9t9klXDnB/YnKOBQ0GoPmoROa4bCq2NeHgJa5ydsQ4mA=="], 399 - 400 - "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.21.0", "", { "dependencies": { "@typescript-eslint/typescript-estree": "8.21.0", "@typescript-eslint/utils": "8.21.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-95OsL6J2BtzoBxHicoXHxgk3z+9P3BEcQTpBKriqiYzLKnM2DeSqs+sndMKdamU8FosiadQFT3D+BSL9EKnAJQ=="], 401 - 402 - "@typescript-eslint/types": ["@typescript-eslint/types@8.21.0", "", {}, "sha512-PAL6LUuQwotLW2a8VsySDBwYMm129vFm4tMVlylzdoTybTHaAi0oBp7Ac6LhSrHHOdLM3efH+nAR6hAWoMF89A=="], 403 - 404 - "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.21.0", "", { "dependencies": { "@typescript-eslint/types": "8.21.0", "@typescript-eslint/visitor-keys": "8.21.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.0.0" }, "peerDependencies": { "typescript": ">=4.8.4 <5.8.0" } }, "sha512-x+aeKh/AjAArSauz0GiQZsjT8ciadNMHdkUSwBB9Z6PrKc/4knM4g3UfHml6oDJmKC88a6//cdxnO/+P2LkMcg=="], 405 - 406 - "@typescript-eslint/utils": ["@typescript-eslint/utils@8.21.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "8.21.0", "@typescript-eslint/types": "8.21.0", "@typescript-eslint/typescript-estree": "8.21.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-xcXBfcq0Kaxgj7dwejMbFyq7IOHgpNMtVuDveK7w3ZGwG9owKzhALVwKpTF2yrZmEwl9SWdetf3fxNzJQaVuxw=="], 407 - 408 - "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.21.0", "", { "dependencies": { "@typescript-eslint/types": "8.21.0", "eslint-visitor-keys": "^4.2.0" } }, "sha512-BkLMNpdV6prozk8LlyK/SOoWLmUFi+ZD+pcqti9ILCbVvHGk1ui1g4jJOc2WDLaeExz2qWwojxlPce5PljcT3w=="], 409 - 410 - "@vitejs/plugin-react": ["@vitejs/plugin-react@4.3.4", "", { "dependencies": { "@babel/core": "^7.26.0", "@babel/plugin-transform-react-jsx-self": "^7.25.9", "@babel/plugin-transform-react-jsx-source": "^7.25.9", "@types/babel__core": "^7.20.5", "react-refresh": "^0.14.2" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" } }, "sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug=="], 411 - 412 - "acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], 413 - 414 - "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], 415 - 416 - "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], 417 - 418 - "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], 419 - 420 - "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], 421 - 422 - "aria-hidden": ["aria-hidden@1.2.4", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A=="], 423 - 424 - "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], 425 - 426 - "axios": ["axios@1.7.9", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw=="], 427 - 428 - "babel-plugin-macros": ["babel-plugin-macros@3.1.0", "", { "dependencies": { "@babel/runtime": "^7.12.5", "cosmiconfig": "^7.0.0", "resolve": "^1.19.0" } }, "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg=="], 429 - 430 - "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], 431 - 432 - "brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], 433 - 434 - "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], 435 - 436 - "browserslist": ["browserslist@4.24.4", "", { "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" } }, "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A=="], 437 - 438 - "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], 439 - 440 - "caniuse-lite": ["caniuse-lite@1.0.30001695", "", {}, "sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw=="], 441 - 442 - "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], 443 - 444 - "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="], 445 - 446 - "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], 447 - 448 - "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], 449 - 450 - "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], 451 - 452 - "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], 453 - 454 - "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], 455 - 456 - "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], 457 - 458 - "cosmiconfig": ["cosmiconfig@7.1.0", "", { "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", "parse-json": "^5.0.0", "path-type": "^4.0.0", "yaml": "^1.10.0" } }, "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA=="], 459 - 460 - "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], 461 - 462 - "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], 463 - 464 - "d3-array": ["d3-array@3.2.4", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="], 465 - 466 - "d3-color": ["d3-color@3.1.0", "", {}, "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA=="], 467 - 468 - "d3-ease": ["d3-ease@3.0.1", "", {}, "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w=="], 469 - 470 - "d3-format": ["d3-format@3.1.0", "", {}, "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA=="], 471 - 472 - "d3-interpolate": ["d3-interpolate@3.0.1", "", { "dependencies": { "d3-color": "1 - 3" } }, "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g=="], 473 - 474 - "d3-path": ["d3-path@3.1.0", "", {}, "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ=="], 475 - 476 - "d3-scale": ["d3-scale@4.0.2", "", { "dependencies": { "d3-array": "2.10.0 - 3", "d3-format": "1 - 3", "d3-interpolate": "1.2.0 - 3", "d3-time": "2.1.1 - 3", "d3-time-format": "2 - 4" } }, "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ=="], 477 - 478 - "d3-shape": ["d3-shape@3.2.0", "", { "dependencies": { "d3-path": "^3.1.0" } }, "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA=="], 479 - 480 - "d3-time": ["d3-time@3.1.0", "", { "dependencies": { "d3-array": "2 - 3" } }, "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q=="], 481 - 482 - "d3-time-format": ["d3-time-format@4.1.0", "", { "dependencies": { "d3-time": "1 - 3" } }, "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg=="], 483 - 484 - "d3-timer": ["d3-timer@3.0.1", "", {}, "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA=="], 485 - 486 - "debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="], 487 - 488 - "decimal.js-light": ["decimal.js-light@2.5.1", "", {}, "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg=="], 489 - 490 - "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], 491 - 492 - "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], 493 - 494 - "detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="], 495 - 496 - "detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="], 497 - 498 - "dom-helpers": ["dom-helpers@5.2.1", "", { "dependencies": { "@babel/runtime": "^7.8.7", "csstype": "^3.0.2" } }, "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA=="], 499 - 500 - "electron-to-chromium": ["electron-to-chromium@1.5.88", "", {}, "sha512-K3C2qf1o+bGzbilTDCTBhTQcMS9KW60yTAaTeeXsfvQuTDDwlokLam/AdqlqcSy9u4UainDgsHV23ksXAOgamw=="], 501 - 502 - "enhanced-resolve": ["enhanced-resolve@5.18.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ=="], 503 - 504 - "error-ex": ["error-ex@1.3.2", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g=="], 505 - 506 - "esbuild": ["esbuild@0.24.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.24.2", "@esbuild/android-arm": "0.24.2", "@esbuild/android-arm64": "0.24.2", "@esbuild/android-x64": "0.24.2", "@esbuild/darwin-arm64": "0.24.2", "@esbuild/darwin-x64": "0.24.2", "@esbuild/freebsd-arm64": "0.24.2", "@esbuild/freebsd-x64": "0.24.2", "@esbuild/linux-arm": "0.24.2", "@esbuild/linux-arm64": "0.24.2", "@esbuild/linux-ia32": "0.24.2", "@esbuild/linux-loong64": "0.24.2", "@esbuild/linux-mips64el": "0.24.2", "@esbuild/linux-ppc64": "0.24.2", "@esbuild/linux-riscv64": "0.24.2", "@esbuild/linux-s390x": "0.24.2", "@esbuild/linux-x64": "0.24.2", "@esbuild/netbsd-arm64": "0.24.2", "@esbuild/netbsd-x64": "0.24.2", "@esbuild/openbsd-arm64": "0.24.2", "@esbuild/openbsd-x64": "0.24.2", "@esbuild/sunos-x64": "0.24.2", "@esbuild/win32-arm64": "0.24.2", "@esbuild/win32-ia32": "0.24.2", "@esbuild/win32-x64": "0.24.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA=="], 507 - 508 - "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], 509 - 510 - "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], 511 - 512 - "eslint": ["eslint@9.19.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.0", "@eslint/core": "^0.10.0", "@eslint/eslintrc": "^3.2.0", "@eslint/js": "9.19.0", "@eslint/plugin-kit": "^0.2.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.1", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.2.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA=="], 513 - 514 - "eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@5.1.0", "", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw=="], 515 - 516 - "eslint-plugin-react-refresh": ["eslint-plugin-react-refresh@0.4.18", "", { "peerDependencies": { "eslint": ">=8.40" } }, "sha512-IRGEoFn3OKalm3hjfolEWGqoF/jPqeEYFp+C8B0WMzwGwBMvlRDQd06kghDhF0C61uJ6WfSDhEZE/sAQjduKgw=="], 517 - 518 - "eslint-scope": ["eslint-scope@8.2.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A=="], 519 - 520 - "eslint-visitor-keys": ["eslint-visitor-keys@4.2.0", "", {}, "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw=="], 521 - 522 - "espree": ["espree@10.3.0", "", { "dependencies": { "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.0" } }, "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg=="], 523 - 524 - "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], 525 - 526 - "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], 527 - 528 - "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], 529 - 530 - "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], 531 - 532 - "eventemitter3": ["eventemitter3@4.0.7", "", {}, "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="], 533 - 534 - "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], 535 - 536 - "fast-equals": ["fast-equals@5.2.2", "", {}, "sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw=="], 537 - 538 - "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], 539 - 540 - "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], 541 - 542 - "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], 543 - 544 - "fastq": ["fastq@1.18.0", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw=="], 545 - 546 - "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], 547 - 548 - "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], 549 - 550 - "find-root": ["find-root@1.1.0", "", {}, "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="], 551 - 552 - "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], 553 - 554 - "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], 555 - 556 - "flatted": ["flatted@3.3.2", "", {}, "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA=="], 557 - 558 - "follow-redirects": ["follow-redirects@1.15.9", "", {}, "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="], 559 - 560 - "form-data": ["form-data@4.0.1", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "mime-types": "^2.1.12" } }, "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw=="], 561 - 562 - "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], 563 - 564 - "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], 565 - 566 - "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], 567 - 568 - "get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="], 569 - 570 - "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], 571 - 572 - "globals": ["globals@15.14.0", "", {}, "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig=="], 573 - 574 - "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], 575 - 576 - "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], 577 - 578 - "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], 579 - 580 - "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], 581 - 582 - "hoist-non-react-statics": ["hoist-non-react-statics@3.3.2", "", { "dependencies": { "react-is": "^16.7.0" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="], 583 - 584 - "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], 585 - 586 - "import-fresh": ["import-fresh@3.3.0", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw=="], 587 - 588 - "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], 589 - 590 - "internmap": ["internmap@2.0.3", "", {}, "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="], 591 - 592 - "is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="], 593 - 594 - "is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="], 595 - 596 - "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], 597 - 598 - "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], 599 - 600 - "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], 601 - 602 - "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], 603 - 604 - "jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="], 605 - 606 - "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], 607 - 608 - "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], 609 - 610 - "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], 611 - 612 - "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], 613 - 614 - "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], 615 - 616 - "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], 617 - 618 - "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], 619 - 620 - "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], 621 - 622 - "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], 623 - 624 - "klona": ["klona@2.0.6", "", {}, "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA=="], 625 - 626 - "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], 627 - 628 - "lightningcss": ["lightningcss@1.29.1", "", { "dependencies": { "detect-libc": "^1.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.29.1", "lightningcss-darwin-x64": "1.29.1", "lightningcss-freebsd-x64": "1.29.1", "lightningcss-linux-arm-gnueabihf": "1.29.1", "lightningcss-linux-arm64-gnu": "1.29.1", "lightningcss-linux-arm64-musl": "1.29.1", "lightningcss-linux-x64-gnu": "1.29.1", "lightningcss-linux-x64-musl": "1.29.1", "lightningcss-win32-arm64-msvc": "1.29.1", "lightningcss-win32-x64-msvc": "1.29.1" } }, "sha512-FmGoeD4S05ewj+AkhTY+D+myDvXI6eL27FjHIjoyUkO/uw7WZD1fBVs0QxeYWa7E17CUHJaYX/RUGISCtcrG4Q=="], 629 - 630 - "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.29.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-HtR5XJ5A0lvCqYAoSv2QdZZyoHNttBpa5EP9aNuzBQeKGfbyH5+UipLWvVzpP4Uml5ej4BYs5I9Lco9u1fECqw=="], 631 - 632 - "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.29.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-k33G9IzKUpHy/J/3+9MCO4e+PzaFblsgBjSGlpAaFikeBFm8B/CkO3cKU9oI4g+fjS2KlkLM/Bza9K/aw8wsNA=="], 633 - 634 - "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.29.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-0SUW22fv/8kln2LnIdOCmSuXnxgxVC276W5KLTwoehiO0hxkacBxjHOL5EtHD8BAXg2BvuhsJPmVMasvby3LiQ=="], 635 - 636 - "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.29.1", "", { "os": "linux", "cpu": "arm" }, "sha512-sD32pFvlR0kDlqsOZmYqH/68SqUMPNj+0pucGxToXZi4XZgZmqeX/NkxNKCPsswAXU3UeYgDSpGhu05eAufjDg=="], 637 - 638 - "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.29.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-0+vClRIZ6mmJl/dxGuRsE197o1HDEeeRk6nzycSy2GofC2JsY4ifCRnvUWf/CUBQmlrvMzt6SMQNMSEu22csWQ=="], 639 - 640 - "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.29.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-UKMFrG4rL/uHNgelBsDwJcBqVpzNJbzsKkbI3Ja5fg00sgQnHw/VrzUTEc4jhZ+AN2BvQYz/tkHu4vt1kLuJyw=="], 641 - 642 - "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.29.1", "", { "os": "linux", "cpu": "x64" }, "sha512-u1S+xdODy/eEtjADqirA774y3jLcm8RPtYztwReEXoZKdzgsHYPl0s5V52Tst+GKzqjebkULT86XMSxejzfISw=="], 643 - 644 - "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.29.1", "", { "os": "linux", "cpu": "x64" }, "sha512-L0Tx0DtaNUTzXv0lbGCLB/c/qEADanHbu4QdcNOXLIe1i8i22rZRpbT3gpWYsCh9aSL9zFujY/WmEXIatWvXbw=="], 645 - 646 - "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.29.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-QoOVnkIEFfbW4xPi+dpdft/zAKmgLgsRHfJalEPYuJDOWf7cLQzYg0DEh8/sn737FaeMJxHZRc1oBreiwZCjog=="], 647 - 648 - "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.29.1", "", { "os": "win32", "cpu": "x64" }, "sha512-NygcbThNBe4JElP+olyTI/doBNGJvLs3bFCRPdvuCcxZCcCZ71B858IHpdm7L1btZex0FvCmM17FK98Y9MRy1Q=="], 649 - 650 - "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], 651 - 652 - "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], 653 - 654 - "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], 655 - 656 - "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], 657 - 658 - "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="], 659 - 660 - "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], 661 - 662 - "lucide-react": ["lucide-react@0.474.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-CmghgHkh0OJNmxGKWc0qfPJCYHASPMVSyGY8fj3xgk4v84ItqDg64JNKFZn5hC6E0vHi6gxnbCgwhyVB09wQtA=="], 663 - 664 - "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], 665 - 666 - "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], 667 - 668 - "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], 669 - 670 - "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], 671 - 672 - "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], 673 - 674 - "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], 675 - 676 - "nanoid": ["nanoid@3.3.8", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w=="], 677 - 678 - "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], 679 - 680 - "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], 681 - 682 - "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], 683 - 684 - "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], 685 - 686 - "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], 687 - 688 - "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], 689 - 690 - "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], 691 - 692 - "parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], 693 - 694 - "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], 695 - 696 - "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], 697 - 698 - "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], 699 - 700 - "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="], 701 - 702 - "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], 703 - 704 - "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], 705 - 706 - "postcss": ["postcss@8.5.1", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ=="], 707 - 708 - "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], 709 - 710 - "prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], 711 - 712 - "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], 713 - 714 - "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], 715 - 716 - "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], 717 - 718 - "react": ["react@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ=="], 719 - 720 - "react-dom": ["react-dom@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" }, "peerDependencies": { "react": "^18.3.1" } }, "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw=="], 721 - 722 - "react-hook-form": ["react-hook-form@7.54.2", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-eHpAUgUjWbZocoQYUHposymRb4ZP6d0uwUnooL2uOybA9/3tPUvoAKqEWK1WaSiTxxOfTpffNZP7QwlnM3/gEg=="], 723 - 724 - "react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="], 725 - 726 - "react-number-format": ["react-number-format@5.4.3", "", { "peerDependencies": { "react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-VCY5hFg/soBighAoGcdE+GagkJq0230qN6jcS5sp8wQX1qy1fYN/RX7/BXkrs0oyzzwqR8/+eSUrqXbGeywdUQ=="], 727 - 728 - "react-refresh": ["react-refresh@0.14.2", "", {}, "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA=="], 729 - 730 - "react-remove-scroll": ["react-remove-scroll@2.6.3", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ=="], 731 - 732 - "react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="], 733 - 734 - "react-smooth": ["react-smooth@4.0.4", "", { "dependencies": { "fast-equals": "^5.0.1", "prop-types": "^15.8.1", "react-transition-group": "^4.4.5" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q=="], 735 - 736 - "react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="], 737 - 738 - "react-textarea-autosize": ["react-textarea-autosize@8.5.6", "", { "dependencies": { "@babel/runtime": "^7.20.13", "use-composed-ref": "^1.3.0", "use-latest": "^1.2.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-aT3ioKXMa8f6zHYGebhbdMD2L00tKeRX1zuVuDx9YQK/JLLRSaSxq3ugECEmUB9z2kvk6bFSIoRHLkkUv0RJiw=="], 739 - 740 - "react-transition-group": ["react-transition-group@4.4.5", "", { "dependencies": { "@babel/runtime": "^7.5.5", "dom-helpers": "^5.0.1", "loose-envify": "^1.4.0", "prop-types": "^15.6.2" }, "peerDependencies": { "react": ">=16.6.0", "react-dom": ">=16.6.0" } }, "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g=="], 741 - 742 - "recharts": ["recharts@2.15.0", "", { "dependencies": { "clsx": "^2.0.0", "eventemitter3": "^4.0.1", "lodash": "^4.17.21", "react-is": "^18.3.1", "react-smooth": "^4.0.0", "recharts-scale": "^0.4.4", "tiny-invariant": "^1.3.1", "victory-vendor": "^36.6.8" }, "peerDependencies": { "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-cIvMxDfpAmqAmVgc4yb7pgm/O1tmmkl/CjrvXuW+62/+7jj/iF9Ykm+hb/UJt42TREHMyd3gb+pkgoa2MxgDIw=="], 743 - 744 - "recharts-scale": ["recharts-scale@0.4.5", "", { "dependencies": { "decimal.js-light": "^2.4.1" } }, "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w=="], 745 - 746 - "regenerator-runtime": ["regenerator-runtime@0.14.1", "", {}, "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="], 747 - 748 - "resolve": ["resolve@1.22.10", "", { "dependencies": { "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w=="], 749 - 750 - "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], 751 - 752 - "reusify": ["reusify@1.0.4", "", {}, "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="], 753 - 754 - "rollup": ["rollup@4.32.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.32.0", "@rollup/rollup-android-arm64": "4.32.0", "@rollup/rollup-darwin-arm64": "4.32.0", "@rollup/rollup-darwin-x64": "4.32.0", "@rollup/rollup-freebsd-arm64": "4.32.0", "@rollup/rollup-freebsd-x64": "4.32.0", "@rollup/rollup-linux-arm-gnueabihf": "4.32.0", "@rollup/rollup-linux-arm-musleabihf": "4.32.0", "@rollup/rollup-linux-arm64-gnu": "4.32.0", "@rollup/rollup-linux-arm64-musl": "4.32.0", "@rollup/rollup-linux-loongarch64-gnu": "4.32.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.32.0", "@rollup/rollup-linux-riscv64-gnu": "4.32.0", "@rollup/rollup-linux-s390x-gnu": "4.32.0", "@rollup/rollup-linux-x64-gnu": "4.32.0", "@rollup/rollup-linux-x64-musl": "4.32.0", "@rollup/rollup-win32-arm64-msvc": "4.32.0", "@rollup/rollup-win32-ia32-msvc": "4.32.0", "@rollup/rollup-win32-x64-msvc": "4.32.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-JmrhfQR31Q4AuNBjjAX4s+a/Pu/Q8Q9iwjWBsjRH1q52SPFE2NqRMK6fUZKKnvKO6id+h7JIRf0oYsph53eATg=="], 755 - 756 - "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], 757 - 758 - "scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], 759 - 760 - "semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], 761 - 762 - "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], 763 - 764 - "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], 765 - 766 - "source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="], 767 - 768 - "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], 769 - 770 - "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], 771 - 772 - "stylis": ["stylis@4.2.0", "", {}, "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="], 773 - 774 - "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], 775 - 776 - "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], 777 - 778 - "tabbable": ["tabbable@6.2.0", "", {}, "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="], 779 - 780 - "tailwind-merge": ["tailwind-merge@2.6.0", "", {}, "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA=="], 781 - 782 - "tailwindcss": ["tailwindcss@4.0.0", "", {}, "sha512-ULRPI3A+e39T7pSaf1xoi58AqqJxVCLg8F/uM5A3FadUbnyDTgltVnXJvdkTjwCOGA6NazqHVcwPJC5h2vRYVQ=="], 783 - 784 - "tailwindcss-animate": ["tailwindcss-animate@1.0.7", "", { "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" } }, "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA=="], 785 - 786 - "tapable": ["tapable@2.2.1", "", {}, "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="], 787 - 788 - "tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="], 789 - 790 - "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], 791 - 792 - "ts-api-utils": ["ts-api-utils@2.0.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ=="], 793 - 794 - "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], 795 - 796 - "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], 797 - 798 - "type-fest": ["type-fest@4.33.0", "", {}, "sha512-s6zVrxuyKbbAsSAD5ZPTB77q4YIdRctkTbJ2/Dqlinwz+8ooH2gd+YA7VA6Pa93KML9GockVvoxjZ2vHP+mu8g=="], 799 - 800 - "typescript": ["typescript@5.6.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw=="], 801 - 802 - "typescript-eslint": ["typescript-eslint@8.21.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.21.0", "@typescript-eslint/parser": "8.21.0", "@typescript-eslint/utils": "8.21.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-txEKYY4XMKwPXxNkN8+AxAdX6iIJAPiJbHE/FpQccs/sxw8Lf26kqwC3cn0xkHlW8kEbLhkhCsjWuMveaY9Rxw=="], 803 - 804 - "undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], 805 - 806 - "update-browserslist-db": ["update-browserslist-db@1.1.2", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg=="], 807 - 808 - "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], 809 - 810 - "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="], 811 - 812 - "use-composed-ref": ["use-composed-ref@1.4.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w=="], 813 - 814 - "use-isomorphic-layout-effect": ["use-isomorphic-layout-effect@1.2.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-q6ayo8DWoPZT0VdG4u3D3uxcgONP3Mevx2i2b0434cwWBoL+aelL1DzkXI6w3PhTZzUeR2kaVlZn70iCiseP6w=="], 815 - 816 - "use-latest": ["use-latest@1.3.0", "", { "dependencies": { "use-isomorphic-layout-effect": "^1.1.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ=="], 817 - 818 - "use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="], 819 - 820 - "victory-vendor": ["victory-vendor@36.9.2", "", { "dependencies": { "@types/d3-array": "^3.0.3", "@types/d3-ease": "^3.0.0", "@types/d3-interpolate": "^3.0.1", "@types/d3-scale": "^4.0.2", "@types/d3-shape": "^3.1.0", "@types/d3-time": "^3.0.0", "@types/d3-timer": "^3.0.0", "d3-array": "^3.1.6", "d3-ease": "^3.0.1", "d3-interpolate": "^3.0.1", "d3-scale": "^4.0.2", "d3-shape": "^3.1.0", "d3-time": "^3.0.0", "d3-timer": "^3.0.1" } }, "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ=="], 821 - 822 - "vite": ["vite@6.0.11", "", { "dependencies": { "esbuild": "^0.24.2", "postcss": "^8.4.49", "rollup": "^4.23.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg=="], 823 - 824 - "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], 825 - 826 - "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], 827 - 828 - "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], 829 - 830 - "yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="], 831 - 832 - "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], 833 - 834 - "zod": ["zod@3.24.1", "", {}, "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A=="], 835 - 836 - "@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], 837 - 838 - "@emotion/babel-plugin/convert-source-map": ["convert-source-map@1.9.0", "", {}, "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="], 839 - 840 - "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], 841 - 842 - "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], 843 - 844 - "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="], 845 - 846 - "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], 847 - 848 - "@typescript-eslint/typescript-estree/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], 849 - 850 - "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], 851 - 852 - "hoist-non-react-statics/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], 853 - 854 - "prop-types/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], 855 - 856 - "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], 857 - } 858 - }
+14 -11
frontend/index.html
··· 1 1 <!doctype html> 2 2 <html lang="en"> 3 - <head> 4 - <meta charset="UTF-8" /> 5 - <link rel="icon" type="image/svg+xml" href="/vite.svg" /> 6 - <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 7 - <title>Vite + React + TS</title> 8 - </head> 9 - <body> 10 - <div id="root"></div> 11 - <script type="module" src="/src/main.tsx"></script> 12 - </body> 13 - </html> 3 + 4 + <head> 5 + <meta charset="UTF-8" /> 6 + <link rel="icon" type="image/svg+xml" href="/vite.svg" /> 7 + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 8 + <title>SimpleLink</title> 9 + </head> 10 + 11 + <body> 12 + <div id="root"></div> 13 + <script type="module" src="/src/main.tsx"></script> 14 + </body> 15 + 16 + </html>
-4162
frontend/package-lock.json
··· 1 - { 2 - "name": "frontend", 3 - "version": "0.0.0", 4 - "lockfileVersion": 3, 5 - "requires": true, 6 - "packages": { 7 - "": { 8 - "name": "frontend", 9 - "version": "0.0.0", 10 - "dependencies": { 11 - "@emotion/react": "^11.14.0", 12 - "@headlessui/react": "^2.2.0", 13 - "@hookform/resolvers": "^3.10.0", 14 - "@icons-pack/react-simple-icons": "^11.2.0", 15 - "@mantine/core": "^7.16.1", 16 - "@mantine/form": "^7.16.1", 17 - "@mantine/hooks": "^7.16.1", 18 - "@radix-ui/react-dialog": "^1.1.5", 19 - "@radix-ui/react-dropdown-menu": "^2.1.5", 20 - "@radix-ui/react-label": "^2.1.1", 21 - "@radix-ui/react-slot": "^1.1.1", 22 - "@radix-ui/react-tabs": "^1.1.2", 23 - "@radix-ui/react-toast": "^1.2.5", 24 - "@tailwindcss/vite": "^4.0.0", 25 - "axios": "^1.7.9", 26 - "class-variance-authority": "^0.7.1", 27 - "clsx": "^2.1.1", 28 - "lucide-react": "^0.474.0", 29 - "react": "^18.3.1", 30 - "react-dom": "^18.3.1", 31 - "react-hook-form": "^7.54.2", 32 - "react-simple-icons": "^1.0.0-beta.5", 33 - "recharts": "^2.15.0", 34 - "simple-icons": "^14.4.0", 35 - "tailwind-merge": "^2.6.0", 36 - "tailwindcss-animate": "^1.0.7", 37 - "zod": "^3.24.1" 38 - }, 39 - "devDependencies": { 40 - "@eslint/js": "^9.17.0", 41 - "@tailwindcss/postcss": "^4.0.0", 42 - "@types/node": "^22.10.10", 43 - "@types/react": "^18.3.18", 44 - "@types/react-dom": "^18.3.5", 45 - "@vitejs/plugin-react": "^4.3.4", 46 - "eslint": "^9.17.0", 47 - "eslint-plugin-react-hooks": "^5.0.0", 48 - "eslint-plugin-react-refresh": "^0.4.16", 49 - "globals": "^15.14.0", 50 - "postcss": "^8.5.1", 51 - "tailwindcss": "^4.0.0", 52 - "typescript": "~5.6.2", 53 - "typescript-eslint": "^8.18.2", 54 - "vite": "^6.0.5" 55 - } 56 - }, 57 - "node_modules/@alloc/quick-lru": { 58 - "version": "5.2.0", 59 - "dev": true, 60 - "license": "MIT", 61 - "engines": { 62 - "node": ">=10" 63 - }, 64 - "funding": { 65 - "url": "https://github.com/sponsors/sindresorhus" 66 - } 67 - }, 68 - "node_modules/@ampproject/remapping": { 69 - "version": "2.3.0", 70 - "dev": true, 71 - "license": "Apache-2.0", 72 - "dependencies": { 73 - "@jridgewell/gen-mapping": "^0.3.5", 74 - "@jridgewell/trace-mapping": "^0.3.24" 75 - }, 76 - "engines": { 77 - "node": ">=6.0.0" 78 - } 79 - }, 80 - "node_modules/@babel/code-frame": { 81 - "version": "7.26.2", 82 - "license": "MIT", 83 - "dependencies": { 84 - "@babel/helper-validator-identifier": "^7.25.9", 85 - "js-tokens": "^4.0.0", 86 - "picocolors": "^1.0.0" 87 - }, 88 - "engines": { 89 - "node": ">=6.9.0" 90 - } 91 - }, 92 - "node_modules/@babel/compat-data": { 93 - "version": "7.26.5", 94 - "dev": true, 95 - "license": "MIT", 96 - "engines": { 97 - "node": ">=6.9.0" 98 - } 99 - }, 100 - "node_modules/@babel/core": { 101 - "version": "7.26.7", 102 - "dev": true, 103 - "license": "MIT", 104 - "dependencies": { 105 - "@ampproject/remapping": "^2.2.0", 106 - "@babel/code-frame": "^7.26.2", 107 - "@babel/generator": "^7.26.5", 108 - "@babel/helper-compilation-targets": "^7.26.5", 109 - "@babel/helper-module-transforms": "^7.26.0", 110 - "@babel/helpers": "^7.26.7", 111 - "@babel/parser": "^7.26.7", 112 - "@babel/template": "^7.25.9", 113 - "@babel/traverse": "^7.26.7", 114 - "@babel/types": "^7.26.7", 115 - "convert-source-map": "^2.0.0", 116 - "debug": "^4.1.0", 117 - "gensync": "^1.0.0-beta.2", 118 - "json5": "^2.2.3", 119 - "semver": "^6.3.1" 120 - }, 121 - "engines": { 122 - "node": ">=6.9.0" 123 - }, 124 - "funding": { 125 - "type": "opencollective", 126 - "url": "https://opencollective.com/babel" 127 - } 128 - }, 129 - "node_modules/@babel/generator": { 130 - "version": "7.26.5", 131 - "license": "MIT", 132 - "dependencies": { 133 - "@babel/parser": "^7.26.5", 134 - "@babel/types": "^7.26.5", 135 - "@jridgewell/gen-mapping": "^0.3.5", 136 - "@jridgewell/trace-mapping": "^0.3.25", 137 - "jsesc": "^3.0.2" 138 - }, 139 - "engines": { 140 - "node": ">=6.9.0" 141 - } 142 - }, 143 - "node_modules/@babel/helper-compilation-targets": { 144 - "version": "7.26.5", 145 - "dev": true, 146 - "license": "MIT", 147 - "dependencies": { 148 - "@babel/compat-data": "^7.26.5", 149 - "@babel/helper-validator-option": "^7.25.9", 150 - "browserslist": "^4.24.0", 151 - "lru-cache": "^5.1.1", 152 - "semver": "^6.3.1" 153 - }, 154 - "engines": { 155 - "node": ">=6.9.0" 156 - } 157 - }, 158 - "node_modules/@babel/helper-module-imports": { 159 - "version": "7.25.9", 160 - "license": "MIT", 161 - "dependencies": { 162 - "@babel/traverse": "^7.25.9", 163 - "@babel/types": "^7.25.9" 164 - }, 165 - "engines": { 166 - "node": ">=6.9.0" 167 - } 168 - }, 169 - "node_modules/@babel/helper-module-transforms": { 170 - "version": "7.26.0", 171 - "dev": true, 172 - "license": "MIT", 173 - "dependencies": { 174 - "@babel/helper-module-imports": "^7.25.9", 175 - "@babel/helper-validator-identifier": "^7.25.9", 176 - "@babel/traverse": "^7.25.9" 177 - }, 178 - "engines": { 179 - "node": ">=6.9.0" 180 - }, 181 - "peerDependencies": { 182 - "@babel/core": "^7.0.0" 183 - } 184 - }, 185 - "node_modules/@babel/helper-plugin-utils": { 186 - "version": "7.26.5", 187 - "dev": true, 188 - "license": "MIT", 189 - "engines": { 190 - "node": ">=6.9.0" 191 - } 192 - }, 193 - "node_modules/@babel/helper-string-parser": { 194 - "version": "7.25.9", 195 - "license": "MIT", 196 - "engines": { 197 - "node": ">=6.9.0" 198 - } 199 - }, 200 - "node_modules/@babel/helper-validator-identifier": { 201 - "version": "7.25.9", 202 - "license": "MIT", 203 - "engines": { 204 - "node": ">=6.9.0" 205 - } 206 - }, 207 - "node_modules/@babel/helper-validator-option": { 208 - "version": "7.25.9", 209 - "dev": true, 210 - "license": "MIT", 211 - "engines": { 212 - "node": ">=6.9.0" 213 - } 214 - }, 215 - "node_modules/@babel/helpers": { 216 - "version": "7.26.7", 217 - "dev": true, 218 - "license": "MIT", 219 - "dependencies": { 220 - "@babel/template": "^7.25.9", 221 - "@babel/types": "^7.26.7" 222 - }, 223 - "engines": { 224 - "node": ">=6.9.0" 225 - } 226 - }, 227 - "node_modules/@babel/parser": { 228 - "version": "7.26.7", 229 - "license": "MIT", 230 - "dependencies": { 231 - "@babel/types": "^7.26.7" 232 - }, 233 - "bin": { 234 - "parser": "bin/babel-parser.js" 235 - }, 236 - "engines": { 237 - "node": ">=6.0.0" 238 - } 239 - }, 240 - "node_modules/@babel/plugin-transform-react-jsx-self": { 241 - "version": "7.25.9", 242 - "dev": true, 243 - "license": "MIT", 244 - "dependencies": { 245 - "@babel/helper-plugin-utils": "^7.25.9" 246 - }, 247 - "engines": { 248 - "node": ">=6.9.0" 249 - }, 250 - "peerDependencies": { 251 - "@babel/core": "^7.0.0-0" 252 - } 253 - }, 254 - "node_modules/@babel/plugin-transform-react-jsx-source": { 255 - "version": "7.25.9", 256 - "dev": true, 257 - "license": "MIT", 258 - "dependencies": { 259 - "@babel/helper-plugin-utils": "^7.25.9" 260 - }, 261 - "engines": { 262 - "node": ">=6.9.0" 263 - }, 264 - "peerDependencies": { 265 - "@babel/core": "^7.0.0-0" 266 - } 267 - }, 268 - "node_modules/@babel/runtime": { 269 - "version": "7.26.7", 270 - "license": "MIT", 271 - "dependencies": { 272 - "regenerator-runtime": "^0.14.0" 273 - }, 274 - "engines": { 275 - "node": ">=6.9.0" 276 - } 277 - }, 278 - "node_modules/@babel/template": { 279 - "version": "7.25.9", 280 - "license": "MIT", 281 - "dependencies": { 282 - "@babel/code-frame": "^7.25.9", 283 - "@babel/parser": "^7.25.9", 284 - "@babel/types": "^7.25.9" 285 - }, 286 - "engines": { 287 - "node": ">=6.9.0" 288 - } 289 - }, 290 - "node_modules/@babel/traverse": { 291 - "version": "7.26.7", 292 - "license": "MIT", 293 - "dependencies": { 294 - "@babel/code-frame": "^7.26.2", 295 - "@babel/generator": "^7.26.5", 296 - "@babel/parser": "^7.26.7", 297 - "@babel/template": "^7.25.9", 298 - "@babel/types": "^7.26.7", 299 - "debug": "^4.3.1", 300 - "globals": "^11.1.0" 301 - }, 302 - "engines": { 303 - "node": ">=6.9.0" 304 - } 305 - }, 306 - "node_modules/@babel/traverse/node_modules/globals": { 307 - "version": "11.12.0", 308 - "license": "MIT", 309 - "engines": { 310 - "node": ">=4" 311 - } 312 - }, 313 - "node_modules/@babel/types": { 314 - "version": "7.26.7", 315 - "license": "MIT", 316 - "dependencies": { 317 - "@babel/helper-string-parser": "^7.25.9", 318 - "@babel/helper-validator-identifier": "^7.25.9" 319 - }, 320 - "engines": { 321 - "node": ">=6.9.0" 322 - } 323 - }, 324 - "node_modules/@emotion/babel-plugin": { 325 - "version": "11.13.5", 326 - "license": "MIT", 327 - "dependencies": { 328 - "@babel/helper-module-imports": "^7.16.7", 329 - "@babel/runtime": "^7.18.3", 330 - "@emotion/hash": "^0.9.2", 331 - "@emotion/memoize": "^0.9.0", 332 - "@emotion/serialize": "^1.3.3", 333 - "babel-plugin-macros": "^3.1.0", 334 - "convert-source-map": "^1.5.0", 335 - "escape-string-regexp": "^4.0.0", 336 - "find-root": "^1.1.0", 337 - "source-map": "^0.5.7", 338 - "stylis": "4.2.0" 339 - } 340 - }, 341 - "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": { 342 - "version": "1.9.0", 343 - "license": "MIT" 344 - }, 345 - "node_modules/@emotion/cache": { 346 - "version": "11.14.0", 347 - "license": "MIT", 348 - "dependencies": { 349 - "@emotion/memoize": "^0.9.0", 350 - "@emotion/sheet": "^1.4.0", 351 - "@emotion/utils": "^1.4.2", 352 - "@emotion/weak-memoize": "^0.4.0", 353 - "stylis": "4.2.0" 354 - } 355 - }, 356 - "node_modules/@emotion/hash": { 357 - "version": "0.9.2", 358 - "license": "MIT" 359 - }, 360 - "node_modules/@emotion/memoize": { 361 - "version": "0.9.0", 362 - "license": "MIT" 363 - }, 364 - "node_modules/@emotion/react": { 365 - "version": "11.14.0", 366 - "license": "MIT", 367 - "dependencies": { 368 - "@babel/runtime": "^7.18.3", 369 - "@emotion/babel-plugin": "^11.13.5", 370 - "@emotion/cache": "^11.14.0", 371 - "@emotion/serialize": "^1.3.3", 372 - "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", 373 - "@emotion/utils": "^1.4.2", 374 - "@emotion/weak-memoize": "^0.4.0", 375 - "hoist-non-react-statics": "^3.3.1" 376 - }, 377 - "peerDependencies": { 378 - "react": ">=16.8.0" 379 - }, 380 - "peerDependenciesMeta": { 381 - "@types/react": { 382 - "optional": true 383 - } 384 - } 385 - }, 386 - "node_modules/@emotion/serialize": { 387 - "version": "1.3.3", 388 - "license": "MIT", 389 - "dependencies": { 390 - "@emotion/hash": "^0.9.2", 391 - "@emotion/memoize": "^0.9.0", 392 - "@emotion/unitless": "^0.10.0", 393 - "@emotion/utils": "^1.4.2", 394 - "csstype": "^3.0.2" 395 - } 396 - }, 397 - "node_modules/@emotion/sheet": { 398 - "version": "1.4.0", 399 - "license": "MIT" 400 - }, 401 - "node_modules/@emotion/unitless": { 402 - "version": "0.10.0", 403 - "license": "MIT" 404 - }, 405 - "node_modules/@emotion/use-insertion-effect-with-fallbacks": { 406 - "version": "1.2.0", 407 - "license": "MIT", 408 - "peerDependencies": { 409 - "react": ">=16.8.0" 410 - } 411 - }, 412 - "node_modules/@emotion/utils": { 413 - "version": "1.4.2", 414 - "license": "MIT" 415 - }, 416 - "node_modules/@emotion/weak-memoize": { 417 - "version": "0.4.0", 418 - "license": "MIT" 419 - }, 420 - "node_modules/@esbuild/darwin-arm64": { 421 - "version": "0.24.2", 422 - "cpu": [ 423 - "arm64" 424 - ], 425 - "license": "MIT", 426 - "optional": true, 427 - "os": [ 428 - "darwin" 429 - ], 430 - "engines": { 431 - "node": ">=18" 432 - } 433 - }, 434 - "node_modules/@eslint-community/eslint-utils": { 435 - "version": "4.4.1", 436 - "dev": true, 437 - "license": "MIT", 438 - "dependencies": { 439 - "eslint-visitor-keys": "^3.4.3" 440 - }, 441 - "engines": { 442 - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 443 - }, 444 - "funding": { 445 - "url": "https://opencollective.com/eslint" 446 - }, 447 - "peerDependencies": { 448 - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" 449 - } 450 - }, 451 - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { 452 - "version": "3.4.3", 453 - "dev": true, 454 - "license": "Apache-2.0", 455 - "engines": { 456 - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 457 - }, 458 - "funding": { 459 - "url": "https://opencollective.com/eslint" 460 - } 461 - }, 462 - "node_modules/@eslint-community/regexpp": { 463 - "version": "4.12.1", 464 - "dev": true, 465 - "license": "MIT", 466 - "engines": { 467 - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" 468 - } 469 - }, 470 - "node_modules/@eslint/config-array": { 471 - "version": "0.19.1", 472 - "dev": true, 473 - "license": "Apache-2.0", 474 - "dependencies": { 475 - "@eslint/object-schema": "^2.1.5", 476 - "debug": "^4.3.1", 477 - "minimatch": "^3.1.2" 478 - }, 479 - "engines": { 480 - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 481 - } 482 - }, 483 - "node_modules/@eslint/core": { 484 - "version": "0.10.0", 485 - "dev": true, 486 - "license": "Apache-2.0", 487 - "dependencies": { 488 - "@types/json-schema": "^7.0.15" 489 - }, 490 - "engines": { 491 - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 492 - } 493 - }, 494 - "node_modules/@eslint/eslintrc": { 495 - "version": "3.2.0", 496 - "dev": true, 497 - "license": "MIT", 498 - "dependencies": { 499 - "ajv": "^6.12.4", 500 - "debug": "^4.3.2", 501 - "espree": "^10.0.1", 502 - "globals": "^14.0.0", 503 - "ignore": "^5.2.0", 504 - "import-fresh": "^3.2.1", 505 - "js-yaml": "^4.1.0", 506 - "minimatch": "^3.1.2", 507 - "strip-json-comments": "^3.1.1" 508 - }, 509 - "engines": { 510 - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 511 - }, 512 - "funding": { 513 - "url": "https://opencollective.com/eslint" 514 - } 515 - }, 516 - "node_modules/@eslint/eslintrc/node_modules/globals": { 517 - "version": "14.0.0", 518 - "dev": true, 519 - "license": "MIT", 520 - "engines": { 521 - "node": ">=18" 522 - }, 523 - "funding": { 524 - "url": "https://github.com/sponsors/sindresorhus" 525 - } 526 - }, 527 - "node_modules/@eslint/js": { 528 - "version": "9.19.0", 529 - "dev": true, 530 - "license": "MIT", 531 - "engines": { 532 - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 533 - } 534 - }, 535 - "node_modules/@eslint/object-schema": { 536 - "version": "2.1.5", 537 - "dev": true, 538 - "license": "Apache-2.0", 539 - "engines": { 540 - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 541 - } 542 - }, 543 - "node_modules/@eslint/plugin-kit": { 544 - "version": "0.2.5", 545 - "dev": true, 546 - "license": "Apache-2.0", 547 - "dependencies": { 548 - "@eslint/core": "^0.10.0", 549 - "levn": "^0.4.1" 550 - }, 551 - "engines": { 552 - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 553 - } 554 - }, 555 - "node_modules/@floating-ui/core": { 556 - "version": "1.6.9", 557 - "license": "MIT", 558 - "dependencies": { 559 - "@floating-ui/utils": "^0.2.9" 560 - } 561 - }, 562 - "node_modules/@floating-ui/dom": { 563 - "version": "1.6.13", 564 - "license": "MIT", 565 - "dependencies": { 566 - "@floating-ui/core": "^1.6.0", 567 - "@floating-ui/utils": "^0.2.9" 568 - } 569 - }, 570 - "node_modules/@floating-ui/react": { 571 - "version": "0.26.28", 572 - "license": "MIT", 573 - "dependencies": { 574 - "@floating-ui/react-dom": "^2.1.2", 575 - "@floating-ui/utils": "^0.2.8", 576 - "tabbable": "^6.0.0" 577 - }, 578 - "peerDependencies": { 579 - "react": ">=16.8.0", 580 - "react-dom": ">=16.8.0" 581 - } 582 - }, 583 - "node_modules/@floating-ui/react-dom": { 584 - "version": "2.1.2", 585 - "license": "MIT", 586 - "dependencies": { 587 - "@floating-ui/dom": "^1.0.0" 588 - }, 589 - "peerDependencies": { 590 - "react": ">=16.8.0", 591 - "react-dom": ">=16.8.0" 592 - } 593 - }, 594 - "node_modules/@floating-ui/utils": { 595 - "version": "0.2.9", 596 - "license": "MIT" 597 - }, 598 - "node_modules/@headlessui/react": { 599 - "version": "2.2.0", 600 - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.0.tgz", 601 - "integrity": "sha512-RzCEg+LXsuI7mHiSomsu/gBJSjpupm6A1qIZ5sWjd7JhARNlMiSA4kKfJpCKwU9tE+zMRterhhrP74PvfJrpXQ==", 602 - "license": "MIT", 603 - "dependencies": { 604 - "@floating-ui/react": "^0.26.16", 605 - "@react-aria/focus": "^3.17.1", 606 - "@react-aria/interactions": "^3.21.3", 607 - "@tanstack/react-virtual": "^3.8.1" 608 - }, 609 - "engines": { 610 - "node": ">=10" 611 - }, 612 - "peerDependencies": { 613 - "react": "^18 || ^19 || ^19.0.0-rc", 614 - "react-dom": "^18 || ^19 || ^19.0.0-rc" 615 - } 616 - }, 617 - "node_modules/@hookform/resolvers": { 618 - "version": "3.10.0", 619 - "license": "MIT", 620 - "peerDependencies": { 621 - "react-hook-form": "^7.0.0" 622 - } 623 - }, 624 - "node_modules/@humanfs/core": { 625 - "version": "0.19.1", 626 - "dev": true, 627 - "license": "Apache-2.0", 628 - "engines": { 629 - "node": ">=18.18.0" 630 - } 631 - }, 632 - "node_modules/@humanfs/node": { 633 - "version": "0.16.6", 634 - "dev": true, 635 - "license": "Apache-2.0", 636 - "dependencies": { 637 - "@humanfs/core": "^0.19.1", 638 - "@humanwhocodes/retry": "^0.3.0" 639 - }, 640 - "engines": { 641 - "node": ">=18.18.0" 642 - } 643 - }, 644 - "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { 645 - "version": "0.3.1", 646 - "dev": true, 647 - "license": "Apache-2.0", 648 - "engines": { 649 - "node": ">=18.18" 650 - }, 651 - "funding": { 652 - "type": "github", 653 - "url": "https://github.com/sponsors/nzakas" 654 - } 655 - }, 656 - "node_modules/@humanwhocodes/module-importer": { 657 - "version": "1.0.1", 658 - "dev": true, 659 - "license": "Apache-2.0", 660 - "engines": { 661 - "node": ">=12.22" 662 - }, 663 - "funding": { 664 - "type": "github", 665 - "url": "https://github.com/sponsors/nzakas" 666 - } 667 - }, 668 - "node_modules/@humanwhocodes/retry": { 669 - "version": "0.4.1", 670 - "dev": true, 671 - "license": "Apache-2.0", 672 - "engines": { 673 - "node": ">=18.18" 674 - }, 675 - "funding": { 676 - "type": "github", 677 - "url": "https://github.com/sponsors/nzakas" 678 - } 679 - }, 680 - "node_modules/@icons-pack/react-simple-icons": { 681 - "version": "11.2.0", 682 - "license": "MIT", 683 - "peerDependencies": { 684 - "react": "^16.13 || ^17 || ^18 || ^19" 685 - } 686 - }, 687 - "node_modules/@jridgewell/gen-mapping": { 688 - "version": "0.3.8", 689 - "license": "MIT", 690 - "dependencies": { 691 - "@jridgewell/set-array": "^1.2.1", 692 - "@jridgewell/sourcemap-codec": "^1.4.10", 693 - "@jridgewell/trace-mapping": "^0.3.24" 694 - }, 695 - "engines": { 696 - "node": ">=6.0.0" 697 - } 698 - }, 699 - "node_modules/@jridgewell/resolve-uri": { 700 - "version": "3.1.2", 701 - "license": "MIT", 702 - "engines": { 703 - "node": ">=6.0.0" 704 - } 705 - }, 706 - "node_modules/@jridgewell/set-array": { 707 - "version": "1.2.1", 708 - "license": "MIT", 709 - "engines": { 710 - "node": ">=6.0.0" 711 - } 712 - }, 713 - "node_modules/@jridgewell/sourcemap-codec": { 714 - "version": "1.5.0", 715 - "license": "MIT" 716 - }, 717 - "node_modules/@jridgewell/trace-mapping": { 718 - "version": "0.3.25", 719 - "license": "MIT", 720 - "dependencies": { 721 - "@jridgewell/resolve-uri": "^3.1.0", 722 - "@jridgewell/sourcemap-codec": "^1.4.14" 723 - } 724 - }, 725 - "node_modules/@jxnblk/simple-icons": { 726 - "version": "1.0.0", 727 - "license": "MIT" 728 - }, 729 - "node_modules/@mantine/core": { 730 - "version": "7.16.1", 731 - "license": "MIT", 732 - "dependencies": { 733 - "@floating-ui/react": "^0.26.28", 734 - "clsx": "^2.1.1", 735 - "react-number-format": "^5.4.3", 736 - "react-remove-scroll": "^2.6.2", 737 - "react-textarea-autosize": "8.5.6", 738 - "type-fest": "^4.27.0" 739 - }, 740 - "peerDependencies": { 741 - "@mantine/hooks": "7.16.1", 742 - "react": "^18.x || ^19.x", 743 - "react-dom": "^18.x || ^19.x" 744 - } 745 - }, 746 - "node_modules/@mantine/form": { 747 - "version": "7.16.1", 748 - "license": "MIT", 749 - "dependencies": { 750 - "fast-deep-equal": "^3.1.3", 751 - "klona": "^2.0.6" 752 - }, 753 - "peerDependencies": { 754 - "react": "^18.x || ^19.x" 755 - } 756 - }, 757 - "node_modules/@mantine/hooks": { 758 - "version": "7.16.1", 759 - "license": "MIT", 760 - "peerDependencies": { 761 - "react": "^18.x || ^19.x" 762 - } 763 - }, 764 - "node_modules/@nodelib/fs.scandir": { 765 - "version": "2.1.5", 766 - "dev": true, 767 - "license": "MIT", 768 - "dependencies": { 769 - "@nodelib/fs.stat": "2.0.5", 770 - "run-parallel": "^1.1.9" 771 - }, 772 - "engines": { 773 - "node": ">= 8" 774 - } 775 - }, 776 - "node_modules/@nodelib/fs.stat": { 777 - "version": "2.0.5", 778 - "dev": true, 779 - "license": "MIT", 780 - "engines": { 781 - "node": ">= 8" 782 - } 783 - }, 784 - "node_modules/@nodelib/fs.walk": { 785 - "version": "1.2.8", 786 - "dev": true, 787 - "license": "MIT", 788 - "dependencies": { 789 - "@nodelib/fs.scandir": "2.1.5", 790 - "fastq": "^1.6.0" 791 - }, 792 - "engines": { 793 - "node": ">= 8" 794 - } 795 - }, 796 - "node_modules/@radix-ui/primitive": { 797 - "version": "1.1.1", 798 - "license": "MIT" 799 - }, 800 - "node_modules/@radix-ui/react-arrow": { 801 - "version": "1.1.1", 802 - "license": "MIT", 803 - "dependencies": { 804 - "@radix-ui/react-primitive": "2.0.1" 805 - }, 806 - "peerDependencies": { 807 - "@types/react": "*", 808 - "@types/react-dom": "*", 809 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 810 - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 811 - }, 812 - "peerDependenciesMeta": { 813 - "@types/react": { 814 - "optional": true 815 - }, 816 - "@types/react-dom": { 817 - "optional": true 818 - } 819 - } 820 - }, 821 - "node_modules/@radix-ui/react-collection": { 822 - "version": "1.1.1", 823 - "license": "MIT", 824 - "dependencies": { 825 - "@radix-ui/react-compose-refs": "1.1.1", 826 - "@radix-ui/react-context": "1.1.1", 827 - "@radix-ui/react-primitive": "2.0.1", 828 - "@radix-ui/react-slot": "1.1.1" 829 - }, 830 - "peerDependencies": { 831 - "@types/react": "*", 832 - "@types/react-dom": "*", 833 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 834 - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 835 - }, 836 - "peerDependenciesMeta": { 837 - "@types/react": { 838 - "optional": true 839 - }, 840 - "@types/react-dom": { 841 - "optional": true 842 - } 843 - } 844 - }, 845 - "node_modules/@radix-ui/react-compose-refs": { 846 - "version": "1.1.1", 847 - "license": "MIT", 848 - "peerDependencies": { 849 - "@types/react": "*", 850 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 851 - }, 852 - "peerDependenciesMeta": { 853 - "@types/react": { 854 - "optional": true 855 - } 856 - } 857 - }, 858 - "node_modules/@radix-ui/react-context": { 859 - "version": "1.1.1", 860 - "license": "MIT", 861 - "peerDependencies": { 862 - "@types/react": "*", 863 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 864 - }, 865 - "peerDependenciesMeta": { 866 - "@types/react": { 867 - "optional": true 868 - } 869 - } 870 - }, 871 - "node_modules/@radix-ui/react-dialog": { 872 - "version": "1.1.5", 873 - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.5.tgz", 874 - "integrity": "sha512-LaO3e5h/NOEL4OfXjxD43k9Dx+vn+8n+PCFt6uhX/BADFflllyv3WJG6rgvvSVBxpTch938Qq/LGc2MMxipXPw==", 875 - "license": "MIT", 876 - "dependencies": { 877 - "@radix-ui/primitive": "1.1.1", 878 - "@radix-ui/react-compose-refs": "1.1.1", 879 - "@radix-ui/react-context": "1.1.1", 880 - "@radix-ui/react-dismissable-layer": "1.1.4", 881 - "@radix-ui/react-focus-guards": "1.1.1", 882 - "@radix-ui/react-focus-scope": "1.1.1", 883 - "@radix-ui/react-id": "1.1.0", 884 - "@radix-ui/react-portal": "1.1.3", 885 - "@radix-ui/react-presence": "1.1.2", 886 - "@radix-ui/react-primitive": "2.0.1", 887 - "@radix-ui/react-slot": "1.1.1", 888 - "@radix-ui/react-use-controllable-state": "1.1.0", 889 - "aria-hidden": "^1.2.4", 890 - "react-remove-scroll": "^2.6.2" 891 - }, 892 - "peerDependencies": { 893 - "@types/react": "*", 894 - "@types/react-dom": "*", 895 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 896 - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 897 - }, 898 - "peerDependenciesMeta": { 899 - "@types/react": { 900 - "optional": true 901 - }, 902 - "@types/react-dom": { 903 - "optional": true 904 - } 905 - } 906 - }, 907 - "node_modules/@radix-ui/react-direction": { 908 - "version": "1.1.0", 909 - "license": "MIT", 910 - "peerDependencies": { 911 - "@types/react": "*", 912 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 913 - }, 914 - "peerDependenciesMeta": { 915 - "@types/react": { 916 - "optional": true 917 - } 918 - } 919 - }, 920 - "node_modules/@radix-ui/react-dismissable-layer": { 921 - "version": "1.1.4", 922 - "license": "MIT", 923 - "dependencies": { 924 - "@radix-ui/primitive": "1.1.1", 925 - "@radix-ui/react-compose-refs": "1.1.1", 926 - "@radix-ui/react-primitive": "2.0.1", 927 - "@radix-ui/react-use-callback-ref": "1.1.0", 928 - "@radix-ui/react-use-escape-keydown": "1.1.0" 929 - }, 930 - "peerDependencies": { 931 - "@types/react": "*", 932 - "@types/react-dom": "*", 933 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 934 - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 935 - }, 936 - "peerDependenciesMeta": { 937 - "@types/react": { 938 - "optional": true 939 - }, 940 - "@types/react-dom": { 941 - "optional": true 942 - } 943 - } 944 - }, 945 - "node_modules/@radix-ui/react-dropdown-menu": { 946 - "version": "2.1.5", 947 - "license": "MIT", 948 - "dependencies": { 949 - "@radix-ui/primitive": "1.1.1", 950 - "@radix-ui/react-compose-refs": "1.1.1", 951 - "@radix-ui/react-context": "1.1.1", 952 - "@radix-ui/react-id": "1.1.0", 953 - "@radix-ui/react-menu": "2.1.5", 954 - "@radix-ui/react-primitive": "2.0.1", 955 - "@radix-ui/react-use-controllable-state": "1.1.0" 956 - }, 957 - "peerDependencies": { 958 - "@types/react": "*", 959 - "@types/react-dom": "*", 960 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 961 - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 962 - }, 963 - "peerDependenciesMeta": { 964 - "@types/react": { 965 - "optional": true 966 - }, 967 - "@types/react-dom": { 968 - "optional": true 969 - } 970 - } 971 - }, 972 - "node_modules/@radix-ui/react-focus-guards": { 973 - "version": "1.1.1", 974 - "license": "MIT", 975 - "peerDependencies": { 976 - "@types/react": "*", 977 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 978 - }, 979 - "peerDependenciesMeta": { 980 - "@types/react": { 981 - "optional": true 982 - } 983 - } 984 - }, 985 - "node_modules/@radix-ui/react-focus-scope": { 986 - "version": "1.1.1", 987 - "license": "MIT", 988 - "dependencies": { 989 - "@radix-ui/react-compose-refs": "1.1.1", 990 - "@radix-ui/react-primitive": "2.0.1", 991 - "@radix-ui/react-use-callback-ref": "1.1.0" 992 - }, 993 - "peerDependencies": { 994 - "@types/react": "*", 995 - "@types/react-dom": "*", 996 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 997 - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 998 - }, 999 - "peerDependenciesMeta": { 1000 - "@types/react": { 1001 - "optional": true 1002 - }, 1003 - "@types/react-dom": { 1004 - "optional": true 1005 - } 1006 - } 1007 - }, 1008 - "node_modules/@radix-ui/react-id": { 1009 - "version": "1.1.0", 1010 - "license": "MIT", 1011 - "dependencies": { 1012 - "@radix-ui/react-use-layout-effect": "1.1.0" 1013 - }, 1014 - "peerDependencies": { 1015 - "@types/react": "*", 1016 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1017 - }, 1018 - "peerDependenciesMeta": { 1019 - "@types/react": { 1020 - "optional": true 1021 - } 1022 - } 1023 - }, 1024 - "node_modules/@radix-ui/react-label": { 1025 - "version": "2.1.1", 1026 - "license": "MIT", 1027 - "dependencies": { 1028 - "@radix-ui/react-primitive": "2.0.1" 1029 - }, 1030 - "peerDependencies": { 1031 - "@types/react": "*", 1032 - "@types/react-dom": "*", 1033 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 1034 - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1035 - }, 1036 - "peerDependenciesMeta": { 1037 - "@types/react": { 1038 - "optional": true 1039 - }, 1040 - "@types/react-dom": { 1041 - "optional": true 1042 - } 1043 - } 1044 - }, 1045 - "node_modules/@radix-ui/react-menu": { 1046 - "version": "2.1.5", 1047 - "license": "MIT", 1048 - "dependencies": { 1049 - "@radix-ui/primitive": "1.1.1", 1050 - "@radix-ui/react-collection": "1.1.1", 1051 - "@radix-ui/react-compose-refs": "1.1.1", 1052 - "@radix-ui/react-context": "1.1.1", 1053 - "@radix-ui/react-direction": "1.1.0", 1054 - "@radix-ui/react-dismissable-layer": "1.1.4", 1055 - "@radix-ui/react-focus-guards": "1.1.1", 1056 - "@radix-ui/react-focus-scope": "1.1.1", 1057 - "@radix-ui/react-id": "1.1.0", 1058 - "@radix-ui/react-popper": "1.2.1", 1059 - "@radix-ui/react-portal": "1.1.3", 1060 - "@radix-ui/react-presence": "1.1.2", 1061 - "@radix-ui/react-primitive": "2.0.1", 1062 - "@radix-ui/react-roving-focus": "1.1.1", 1063 - "@radix-ui/react-slot": "1.1.1", 1064 - "@radix-ui/react-use-callback-ref": "1.1.0", 1065 - "aria-hidden": "^1.2.4", 1066 - "react-remove-scroll": "^2.6.2" 1067 - }, 1068 - "peerDependencies": { 1069 - "@types/react": "*", 1070 - "@types/react-dom": "*", 1071 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 1072 - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1073 - }, 1074 - "peerDependenciesMeta": { 1075 - "@types/react": { 1076 - "optional": true 1077 - }, 1078 - "@types/react-dom": { 1079 - "optional": true 1080 - } 1081 - } 1082 - }, 1083 - "node_modules/@radix-ui/react-popper": { 1084 - "version": "1.2.1", 1085 - "license": "MIT", 1086 - "dependencies": { 1087 - "@floating-ui/react-dom": "^2.0.0", 1088 - "@radix-ui/react-arrow": "1.1.1", 1089 - "@radix-ui/react-compose-refs": "1.1.1", 1090 - "@radix-ui/react-context": "1.1.1", 1091 - "@radix-ui/react-primitive": "2.0.1", 1092 - "@radix-ui/react-use-callback-ref": "1.1.0", 1093 - "@radix-ui/react-use-layout-effect": "1.1.0", 1094 - "@radix-ui/react-use-rect": "1.1.0", 1095 - "@radix-ui/react-use-size": "1.1.0", 1096 - "@radix-ui/rect": "1.1.0" 1097 - }, 1098 - "peerDependencies": { 1099 - "@types/react": "*", 1100 - "@types/react-dom": "*", 1101 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 1102 - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1103 - }, 1104 - "peerDependenciesMeta": { 1105 - "@types/react": { 1106 - "optional": true 1107 - }, 1108 - "@types/react-dom": { 1109 - "optional": true 1110 - } 1111 - } 1112 - }, 1113 - "node_modules/@radix-ui/react-portal": { 1114 - "version": "1.1.3", 1115 - "license": "MIT", 1116 - "dependencies": { 1117 - "@radix-ui/react-primitive": "2.0.1", 1118 - "@radix-ui/react-use-layout-effect": "1.1.0" 1119 - }, 1120 - "peerDependencies": { 1121 - "@types/react": "*", 1122 - "@types/react-dom": "*", 1123 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 1124 - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1125 - }, 1126 - "peerDependenciesMeta": { 1127 - "@types/react": { 1128 - "optional": true 1129 - }, 1130 - "@types/react-dom": { 1131 - "optional": true 1132 - } 1133 - } 1134 - }, 1135 - "node_modules/@radix-ui/react-presence": { 1136 - "version": "1.1.2", 1137 - "license": "MIT", 1138 - "dependencies": { 1139 - "@radix-ui/react-compose-refs": "1.1.1", 1140 - "@radix-ui/react-use-layout-effect": "1.1.0" 1141 - }, 1142 - "peerDependencies": { 1143 - "@types/react": "*", 1144 - "@types/react-dom": "*", 1145 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 1146 - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1147 - }, 1148 - "peerDependenciesMeta": { 1149 - "@types/react": { 1150 - "optional": true 1151 - }, 1152 - "@types/react-dom": { 1153 - "optional": true 1154 - } 1155 - } 1156 - }, 1157 - "node_modules/@radix-ui/react-primitive": { 1158 - "version": "2.0.1", 1159 - "license": "MIT", 1160 - "dependencies": { 1161 - "@radix-ui/react-slot": "1.1.1" 1162 - }, 1163 - "peerDependencies": { 1164 - "@types/react": "*", 1165 - "@types/react-dom": "*", 1166 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 1167 - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1168 - }, 1169 - "peerDependenciesMeta": { 1170 - "@types/react": { 1171 - "optional": true 1172 - }, 1173 - "@types/react-dom": { 1174 - "optional": true 1175 - } 1176 - } 1177 - }, 1178 - "node_modules/@radix-ui/react-roving-focus": { 1179 - "version": "1.1.1", 1180 - "license": "MIT", 1181 - "dependencies": { 1182 - "@radix-ui/primitive": "1.1.1", 1183 - "@radix-ui/react-collection": "1.1.1", 1184 - "@radix-ui/react-compose-refs": "1.1.1", 1185 - "@radix-ui/react-context": "1.1.1", 1186 - "@radix-ui/react-direction": "1.1.0", 1187 - "@radix-ui/react-id": "1.1.0", 1188 - "@radix-ui/react-primitive": "2.0.1", 1189 - "@radix-ui/react-use-callback-ref": "1.1.0", 1190 - "@radix-ui/react-use-controllable-state": "1.1.0" 1191 - }, 1192 - "peerDependencies": { 1193 - "@types/react": "*", 1194 - "@types/react-dom": "*", 1195 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 1196 - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1197 - }, 1198 - "peerDependenciesMeta": { 1199 - "@types/react": { 1200 - "optional": true 1201 - }, 1202 - "@types/react-dom": { 1203 - "optional": true 1204 - } 1205 - } 1206 - }, 1207 - "node_modules/@radix-ui/react-slot": { 1208 - "version": "1.1.1", 1209 - "license": "MIT", 1210 - "dependencies": { 1211 - "@radix-ui/react-compose-refs": "1.1.1" 1212 - }, 1213 - "peerDependencies": { 1214 - "@types/react": "*", 1215 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1216 - }, 1217 - "peerDependenciesMeta": { 1218 - "@types/react": { 1219 - "optional": true 1220 - } 1221 - } 1222 - }, 1223 - "node_modules/@radix-ui/react-tabs": { 1224 - "version": "1.1.2", 1225 - "license": "MIT", 1226 - "dependencies": { 1227 - "@radix-ui/primitive": "1.1.1", 1228 - "@radix-ui/react-context": "1.1.1", 1229 - "@radix-ui/react-direction": "1.1.0", 1230 - "@radix-ui/react-id": "1.1.0", 1231 - "@radix-ui/react-presence": "1.1.2", 1232 - "@radix-ui/react-primitive": "2.0.1", 1233 - "@radix-ui/react-roving-focus": "1.1.1", 1234 - "@radix-ui/react-use-controllable-state": "1.1.0" 1235 - }, 1236 - "peerDependencies": { 1237 - "@types/react": "*", 1238 - "@types/react-dom": "*", 1239 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 1240 - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1241 - }, 1242 - "peerDependenciesMeta": { 1243 - "@types/react": { 1244 - "optional": true 1245 - }, 1246 - "@types/react-dom": { 1247 - "optional": true 1248 - } 1249 - } 1250 - }, 1251 - "node_modules/@radix-ui/react-toast": { 1252 - "version": "1.2.5", 1253 - "license": "MIT", 1254 - "dependencies": { 1255 - "@radix-ui/primitive": "1.1.1", 1256 - "@radix-ui/react-collection": "1.1.1", 1257 - "@radix-ui/react-compose-refs": "1.1.1", 1258 - "@radix-ui/react-context": "1.1.1", 1259 - "@radix-ui/react-dismissable-layer": "1.1.4", 1260 - "@radix-ui/react-portal": "1.1.3", 1261 - "@radix-ui/react-presence": "1.1.2", 1262 - "@radix-ui/react-primitive": "2.0.1", 1263 - "@radix-ui/react-use-callback-ref": "1.1.0", 1264 - "@radix-ui/react-use-controllable-state": "1.1.0", 1265 - "@radix-ui/react-use-layout-effect": "1.1.0", 1266 - "@radix-ui/react-visually-hidden": "1.1.1" 1267 - }, 1268 - "peerDependencies": { 1269 - "@types/react": "*", 1270 - "@types/react-dom": "*", 1271 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 1272 - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1273 - }, 1274 - "peerDependenciesMeta": { 1275 - "@types/react": { 1276 - "optional": true 1277 - }, 1278 - "@types/react-dom": { 1279 - "optional": true 1280 - } 1281 - } 1282 - }, 1283 - "node_modules/@radix-ui/react-use-callback-ref": { 1284 - "version": "1.1.0", 1285 - "license": "MIT", 1286 - "peerDependencies": { 1287 - "@types/react": "*", 1288 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1289 - }, 1290 - "peerDependenciesMeta": { 1291 - "@types/react": { 1292 - "optional": true 1293 - } 1294 - } 1295 - }, 1296 - "node_modules/@radix-ui/react-use-controllable-state": { 1297 - "version": "1.1.0", 1298 - "license": "MIT", 1299 - "dependencies": { 1300 - "@radix-ui/react-use-callback-ref": "1.1.0" 1301 - }, 1302 - "peerDependencies": { 1303 - "@types/react": "*", 1304 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1305 - }, 1306 - "peerDependenciesMeta": { 1307 - "@types/react": { 1308 - "optional": true 1309 - } 1310 - } 1311 - }, 1312 - "node_modules/@radix-ui/react-use-escape-keydown": { 1313 - "version": "1.1.0", 1314 - "license": "MIT", 1315 - "dependencies": { 1316 - "@radix-ui/react-use-callback-ref": "1.1.0" 1317 - }, 1318 - "peerDependencies": { 1319 - "@types/react": "*", 1320 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1321 - }, 1322 - "peerDependenciesMeta": { 1323 - "@types/react": { 1324 - "optional": true 1325 - } 1326 - } 1327 - }, 1328 - "node_modules/@radix-ui/react-use-layout-effect": { 1329 - "version": "1.1.0", 1330 - "license": "MIT", 1331 - "peerDependencies": { 1332 - "@types/react": "*", 1333 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1334 - }, 1335 - "peerDependenciesMeta": { 1336 - "@types/react": { 1337 - "optional": true 1338 - } 1339 - } 1340 - }, 1341 - "node_modules/@radix-ui/react-use-rect": { 1342 - "version": "1.1.0", 1343 - "license": "MIT", 1344 - "dependencies": { 1345 - "@radix-ui/rect": "1.1.0" 1346 - }, 1347 - "peerDependencies": { 1348 - "@types/react": "*", 1349 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1350 - }, 1351 - "peerDependenciesMeta": { 1352 - "@types/react": { 1353 - "optional": true 1354 - } 1355 - } 1356 - }, 1357 - "node_modules/@radix-ui/react-use-size": { 1358 - "version": "1.1.0", 1359 - "license": "MIT", 1360 - "dependencies": { 1361 - "@radix-ui/react-use-layout-effect": "1.1.0" 1362 - }, 1363 - "peerDependencies": { 1364 - "@types/react": "*", 1365 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1366 - }, 1367 - "peerDependenciesMeta": { 1368 - "@types/react": { 1369 - "optional": true 1370 - } 1371 - } 1372 - }, 1373 - "node_modules/@radix-ui/react-visually-hidden": { 1374 - "version": "1.1.1", 1375 - "license": "MIT", 1376 - "dependencies": { 1377 - "@radix-ui/react-primitive": "2.0.1" 1378 - }, 1379 - "peerDependencies": { 1380 - "@types/react": "*", 1381 - "@types/react-dom": "*", 1382 - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 1383 - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 1384 - }, 1385 - "peerDependenciesMeta": { 1386 - "@types/react": { 1387 - "optional": true 1388 - }, 1389 - "@types/react-dom": { 1390 - "optional": true 1391 - } 1392 - } 1393 - }, 1394 - "node_modules/@radix-ui/rect": { 1395 - "version": "1.1.0", 1396 - "license": "MIT" 1397 - }, 1398 - "node_modules/@react-aria/focus": { 1399 - "version": "3.19.1", 1400 - "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.19.1.tgz", 1401 - "integrity": "sha512-bix9Bu1Ue7RPcYmjwcjhB14BMu2qzfJ3tMQLqDc9pweJA66nOw8DThy3IfVr8Z7j2PHktOLf9kcbiZpydKHqzg==", 1402 - "license": "Apache-2.0", 1403 - "dependencies": { 1404 - "@react-aria/interactions": "^3.23.0", 1405 - "@react-aria/utils": "^3.27.0", 1406 - "@react-types/shared": "^3.27.0", 1407 - "@swc/helpers": "^0.5.0", 1408 - "clsx": "^2.0.0" 1409 - }, 1410 - "peerDependencies": { 1411 - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", 1412 - "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" 1413 - } 1414 - }, 1415 - "node_modules/@react-aria/interactions": { 1416 - "version": "3.23.0", 1417 - "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.23.0.tgz", 1418 - "integrity": "sha512-0qR1atBIWrb7FzQ+Tmr3s8uH5mQdyRH78n0krYaG8tng9+u1JlSi8DGRSaC9ezKyNB84m7vHT207xnHXGeJ3Fg==", 1419 - "license": "Apache-2.0", 1420 - "dependencies": { 1421 - "@react-aria/ssr": "^3.9.7", 1422 - "@react-aria/utils": "^3.27.0", 1423 - "@react-types/shared": "^3.27.0", 1424 - "@swc/helpers": "^0.5.0" 1425 - }, 1426 - "peerDependencies": { 1427 - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", 1428 - "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" 1429 - } 1430 - }, 1431 - "node_modules/@react-aria/ssr": { 1432 - "version": "3.9.7", 1433 - "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.7.tgz", 1434 - "integrity": "sha512-GQygZaGlmYjmYM+tiNBA5C6acmiDWF52Nqd40bBp0Znk4M4hP+LTmI0lpI1BuKMw45T8RIhrAsICIfKwZvi2Gg==", 1435 - "license": "Apache-2.0", 1436 - "dependencies": { 1437 - "@swc/helpers": "^0.5.0" 1438 - }, 1439 - "engines": { 1440 - "node": ">= 12" 1441 - }, 1442 - "peerDependencies": { 1443 - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" 1444 - } 1445 - }, 1446 - "node_modules/@react-aria/utils": { 1447 - "version": "3.27.0", 1448 - "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.27.0.tgz", 1449 - "integrity": "sha512-p681OtApnKOdbeN8ITfnnYqfdHS0z7GE+4l8EXlfLnr70Rp/9xicBO6d2rU+V/B3JujDw2gPWxYKEnEeh0CGCw==", 1450 - "license": "Apache-2.0", 1451 - "dependencies": { 1452 - "@react-aria/ssr": "^3.9.7", 1453 - "@react-stately/utils": "^3.10.5", 1454 - "@react-types/shared": "^3.27.0", 1455 - "@swc/helpers": "^0.5.0", 1456 - "clsx": "^2.0.0" 1457 - }, 1458 - "peerDependencies": { 1459 - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", 1460 - "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" 1461 - } 1462 - }, 1463 - "node_modules/@react-stately/utils": { 1464 - "version": "3.10.5", 1465 - "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.5.tgz", 1466 - "integrity": "sha512-iMQSGcpaecghDIh3mZEpZfoFH3ExBwTtuBEcvZ2XnGzCgQjeYXcMdIUwAfVQLXFTdHUHGF6Gu6/dFrYsCzySBQ==", 1467 - "license": "Apache-2.0", 1468 - "dependencies": { 1469 - "@swc/helpers": "^0.5.0" 1470 - }, 1471 - "peerDependencies": { 1472 - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" 1473 - } 1474 - }, 1475 - "node_modules/@react-types/shared": { 1476 - "version": "3.27.0", 1477 - "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.27.0.tgz", 1478 - "integrity": "sha512-gvznmLhi6JPEf0bsq7SwRYTHAKKq/wcmKqFez9sRdbED+SPMUmK5omfZ6w3EwUFQHbYUa4zPBYedQ7Knv70RMw==", 1479 - "license": "Apache-2.0", 1480 - "peerDependencies": { 1481 - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" 1482 - } 1483 - }, 1484 - "node_modules/@rollup/rollup-darwin-arm64": { 1485 - "version": "4.32.0", 1486 - "cpu": [ 1487 - "arm64" 1488 - ], 1489 - "license": "MIT", 1490 - "optional": true, 1491 - "os": [ 1492 - "darwin" 1493 - ] 1494 - }, 1495 - "node_modules/@swc/helpers": { 1496 - "version": "0.5.15", 1497 - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", 1498 - "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", 1499 - "license": "Apache-2.0", 1500 - "dependencies": { 1501 - "tslib": "^2.8.0" 1502 - } 1503 - }, 1504 - "node_modules/@tailwindcss/node": { 1505 - "version": "4.0.0", 1506 - "license": "MIT", 1507 - "dependencies": { 1508 - "enhanced-resolve": "^5.18.0", 1509 - "jiti": "^2.4.2", 1510 - "tailwindcss": "4.0.0" 1511 - } 1512 - }, 1513 - "node_modules/@tailwindcss/oxide": { 1514 - "version": "4.0.0", 1515 - "license": "MIT", 1516 - "engines": { 1517 - "node": ">= 10" 1518 - }, 1519 - "optionalDependencies": { 1520 - "@tailwindcss/oxide-android-arm64": "4.0.0", 1521 - "@tailwindcss/oxide-darwin-arm64": "4.0.0", 1522 - "@tailwindcss/oxide-darwin-x64": "4.0.0", 1523 - "@tailwindcss/oxide-freebsd-x64": "4.0.0", 1524 - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.0.0", 1525 - "@tailwindcss/oxide-linux-arm64-gnu": "4.0.0", 1526 - "@tailwindcss/oxide-linux-arm64-musl": "4.0.0", 1527 - "@tailwindcss/oxide-linux-x64-gnu": "4.0.0", 1528 - "@tailwindcss/oxide-linux-x64-musl": "4.0.0", 1529 - "@tailwindcss/oxide-win32-arm64-msvc": "4.0.0", 1530 - "@tailwindcss/oxide-win32-x64-msvc": "4.0.0" 1531 - } 1532 - }, 1533 - "node_modules/@tailwindcss/oxide-darwin-arm64": { 1534 - "version": "4.0.0", 1535 - "cpu": [ 1536 - "arm64" 1537 - ], 1538 - "license": "MIT", 1539 - "optional": true, 1540 - "os": [ 1541 - "darwin" 1542 - ], 1543 - "engines": { 1544 - "node": ">= 10" 1545 - } 1546 - }, 1547 - "node_modules/@tailwindcss/postcss": { 1548 - "version": "4.0.0", 1549 - "dev": true, 1550 - "license": "MIT", 1551 - "dependencies": { 1552 - "@alloc/quick-lru": "^5.2.0", 1553 - "@tailwindcss/node": "^4.0.0", 1554 - "@tailwindcss/oxide": "^4.0.0", 1555 - "lightningcss": "^1.29.1", 1556 - "postcss": "^8.4.41", 1557 - "tailwindcss": "4.0.0" 1558 - } 1559 - }, 1560 - "node_modules/@tailwindcss/vite": { 1561 - "version": "4.0.0", 1562 - "license": "MIT", 1563 - "dependencies": { 1564 - "@tailwindcss/node": "^4.0.0", 1565 - "@tailwindcss/oxide": "^4.0.0", 1566 - "lightningcss": "^1.29.1", 1567 - "tailwindcss": "4.0.0" 1568 - }, 1569 - "peerDependencies": { 1570 - "vite": "^5.2.0 || ^6" 1571 - } 1572 - }, 1573 - "node_modules/@tanstack/react-virtual": { 1574 - "version": "3.11.3", 1575 - "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.11.3.tgz", 1576 - "integrity": "sha512-vCU+OTylXN3hdC8RKg68tPlBPjjxtzon7Ys46MgrSLE+JhSjSTPvoQifV6DQJeJmA8Q3KT6CphJbejupx85vFw==", 1577 - "license": "MIT", 1578 - "dependencies": { 1579 - "@tanstack/virtual-core": "3.11.3" 1580 - }, 1581 - "funding": { 1582 - "type": "github", 1583 - "url": "https://github.com/sponsors/tannerlinsley" 1584 - }, 1585 - "peerDependencies": { 1586 - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", 1587 - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 1588 - } 1589 - }, 1590 - "node_modules/@tanstack/virtual-core": { 1591 - "version": "3.11.3", 1592 - "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.11.3.tgz", 1593 - "integrity": "sha512-v2mrNSnMwnPJtcVqNvV0c5roGCBqeogN8jDtgtuHCphdwBasOZ17x8UV8qpHUh+u0MLfX43c0uUHKje0s+Zb0w==", 1594 - "license": "MIT", 1595 - "funding": { 1596 - "type": "github", 1597 - "url": "https://github.com/sponsors/tannerlinsley" 1598 - } 1599 - }, 1600 - "node_modules/@types/babel__core": { 1601 - "version": "7.20.5", 1602 - "dev": true, 1603 - "license": "MIT", 1604 - "dependencies": { 1605 - "@babel/parser": "^7.20.7", 1606 - "@babel/types": "^7.20.7", 1607 - "@types/babel__generator": "*", 1608 - "@types/babel__template": "*", 1609 - "@types/babel__traverse": "*" 1610 - } 1611 - }, 1612 - "node_modules/@types/babel__generator": { 1613 - "version": "7.6.8", 1614 - "dev": true, 1615 - "license": "MIT", 1616 - "dependencies": { 1617 - "@babel/types": "^7.0.0" 1618 - } 1619 - }, 1620 - "node_modules/@types/babel__template": { 1621 - "version": "7.4.4", 1622 - "dev": true, 1623 - "license": "MIT", 1624 - "dependencies": { 1625 - "@babel/parser": "^7.1.0", 1626 - "@babel/types": "^7.0.0" 1627 - } 1628 - }, 1629 - "node_modules/@types/babel__traverse": { 1630 - "version": "7.20.6", 1631 - "dev": true, 1632 - "license": "MIT", 1633 - "dependencies": { 1634 - "@babel/types": "^7.20.7" 1635 - } 1636 - }, 1637 - "node_modules/@types/d3-array": { 1638 - "version": "3.2.1", 1639 - "license": "MIT" 1640 - }, 1641 - "node_modules/@types/d3-color": { 1642 - "version": "3.1.3", 1643 - "license": "MIT" 1644 - }, 1645 - "node_modules/@types/d3-ease": { 1646 - "version": "3.0.2", 1647 - "license": "MIT" 1648 - }, 1649 - "node_modules/@types/d3-interpolate": { 1650 - "version": "3.0.4", 1651 - "license": "MIT", 1652 - "dependencies": { 1653 - "@types/d3-color": "*" 1654 - } 1655 - }, 1656 - "node_modules/@types/d3-path": { 1657 - "version": "3.1.0", 1658 - "license": "MIT" 1659 - }, 1660 - "node_modules/@types/d3-scale": { 1661 - "version": "4.0.8", 1662 - "license": "MIT", 1663 - "dependencies": { 1664 - "@types/d3-time": "*" 1665 - } 1666 - }, 1667 - "node_modules/@types/d3-shape": { 1668 - "version": "3.1.7", 1669 - "license": "MIT", 1670 - "dependencies": { 1671 - "@types/d3-path": "*" 1672 - } 1673 - }, 1674 - "node_modules/@types/d3-time": { 1675 - "version": "3.0.4", 1676 - "license": "MIT" 1677 - }, 1678 - "node_modules/@types/d3-timer": { 1679 - "version": "3.0.2", 1680 - "license": "MIT" 1681 - }, 1682 - "node_modules/@types/estree": { 1683 - "version": "1.0.6", 1684 - "license": "MIT" 1685 - }, 1686 - "node_modules/@types/json-schema": { 1687 - "version": "7.0.15", 1688 - "dev": true, 1689 - "license": "MIT" 1690 - }, 1691 - "node_modules/@types/node": { 1692 - "version": "22.10.10", 1693 - "devOptional": true, 1694 - "license": "MIT", 1695 - "dependencies": { 1696 - "undici-types": "~6.20.0" 1697 - } 1698 - }, 1699 - "node_modules/@types/parse-json": { 1700 - "version": "4.0.2", 1701 - "license": "MIT" 1702 - }, 1703 - "node_modules/@types/prop-types": { 1704 - "version": "15.7.14", 1705 - "devOptional": true, 1706 - "license": "MIT" 1707 - }, 1708 - "node_modules/@types/react": { 1709 - "version": "18.3.18", 1710 - "devOptional": true, 1711 - "license": "MIT", 1712 - "dependencies": { 1713 - "@types/prop-types": "*", 1714 - "csstype": "^3.0.2" 1715 - } 1716 - }, 1717 - "node_modules/@types/react-dom": { 1718 - "version": "18.3.5", 1719 - "devOptional": true, 1720 - "license": "MIT", 1721 - "peerDependencies": { 1722 - "@types/react": "^18.0.0" 1723 - } 1724 - }, 1725 - "node_modules/@typescript-eslint/eslint-plugin": { 1726 - "version": "8.21.0", 1727 - "dev": true, 1728 - "license": "MIT", 1729 - "dependencies": { 1730 - "@eslint-community/regexpp": "^4.10.0", 1731 - "@typescript-eslint/scope-manager": "8.21.0", 1732 - "@typescript-eslint/type-utils": "8.21.0", 1733 - "@typescript-eslint/utils": "8.21.0", 1734 - "@typescript-eslint/visitor-keys": "8.21.0", 1735 - "graphemer": "^1.4.0", 1736 - "ignore": "^5.3.1", 1737 - "natural-compare": "^1.4.0", 1738 - "ts-api-utils": "^2.0.0" 1739 - }, 1740 - "engines": { 1741 - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 1742 - }, 1743 - "funding": { 1744 - "type": "opencollective", 1745 - "url": "https://opencollective.com/typescript-eslint" 1746 - }, 1747 - "peerDependencies": { 1748 - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", 1749 - "eslint": "^8.57.0 || ^9.0.0", 1750 - "typescript": ">=4.8.4 <5.8.0" 1751 - } 1752 - }, 1753 - "node_modules/@typescript-eslint/parser": { 1754 - "version": "8.21.0", 1755 - "dev": true, 1756 - "license": "MIT", 1757 - "dependencies": { 1758 - "@typescript-eslint/scope-manager": "8.21.0", 1759 - "@typescript-eslint/types": "8.21.0", 1760 - "@typescript-eslint/typescript-estree": "8.21.0", 1761 - "@typescript-eslint/visitor-keys": "8.21.0", 1762 - "debug": "^4.3.4" 1763 - }, 1764 - "engines": { 1765 - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 1766 - }, 1767 - "funding": { 1768 - "type": "opencollective", 1769 - "url": "https://opencollective.com/typescript-eslint" 1770 - }, 1771 - "peerDependencies": { 1772 - "eslint": "^8.57.0 || ^9.0.0", 1773 - "typescript": ">=4.8.4 <5.8.0" 1774 - } 1775 - }, 1776 - "node_modules/@typescript-eslint/scope-manager": { 1777 - "version": "8.21.0", 1778 - "dev": true, 1779 - "license": "MIT", 1780 - "dependencies": { 1781 - "@typescript-eslint/types": "8.21.0", 1782 - "@typescript-eslint/visitor-keys": "8.21.0" 1783 - }, 1784 - "engines": { 1785 - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 1786 - }, 1787 - "funding": { 1788 - "type": "opencollective", 1789 - "url": "https://opencollective.com/typescript-eslint" 1790 - } 1791 - }, 1792 - "node_modules/@typescript-eslint/type-utils": { 1793 - "version": "8.21.0", 1794 - "dev": true, 1795 - "license": "MIT", 1796 - "dependencies": { 1797 - "@typescript-eslint/typescript-estree": "8.21.0", 1798 - "@typescript-eslint/utils": "8.21.0", 1799 - "debug": "^4.3.4", 1800 - "ts-api-utils": "^2.0.0" 1801 - }, 1802 - "engines": { 1803 - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 1804 - }, 1805 - "funding": { 1806 - "type": "opencollective", 1807 - "url": "https://opencollective.com/typescript-eslint" 1808 - }, 1809 - "peerDependencies": { 1810 - "eslint": "^8.57.0 || ^9.0.0", 1811 - "typescript": ">=4.8.4 <5.8.0" 1812 - } 1813 - }, 1814 - "node_modules/@typescript-eslint/types": { 1815 - "version": "8.21.0", 1816 - "dev": true, 1817 - "license": "MIT", 1818 - "engines": { 1819 - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 1820 - }, 1821 - "funding": { 1822 - "type": "opencollective", 1823 - "url": "https://opencollective.com/typescript-eslint" 1824 - } 1825 - }, 1826 - "node_modules/@typescript-eslint/typescript-estree": { 1827 - "version": "8.21.0", 1828 - "dev": true, 1829 - "license": "MIT", 1830 - "dependencies": { 1831 - "@typescript-eslint/types": "8.21.0", 1832 - "@typescript-eslint/visitor-keys": "8.21.0", 1833 - "debug": "^4.3.4", 1834 - "fast-glob": "^3.3.2", 1835 - "is-glob": "^4.0.3", 1836 - "minimatch": "^9.0.4", 1837 - "semver": "^7.6.0", 1838 - "ts-api-utils": "^2.0.0" 1839 - }, 1840 - "engines": { 1841 - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 1842 - }, 1843 - "funding": { 1844 - "type": "opencollective", 1845 - "url": "https://opencollective.com/typescript-eslint" 1846 - }, 1847 - "peerDependencies": { 1848 - "typescript": ">=4.8.4 <5.8.0" 1849 - } 1850 - }, 1851 - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { 1852 - "version": "9.0.5", 1853 - "dev": true, 1854 - "license": "ISC", 1855 - "dependencies": { 1856 - "brace-expansion": "^2.0.1" 1857 - }, 1858 - "engines": { 1859 - "node": ">=16 || 14 >=14.17" 1860 - }, 1861 - "funding": { 1862 - "url": "https://github.com/sponsors/isaacs" 1863 - } 1864 - }, 1865 - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch/node_modules/brace-expansion": { 1866 - "version": "2.0.1", 1867 - "dev": true, 1868 - "license": "MIT", 1869 - "dependencies": { 1870 - "balanced-match": "^1.0.0" 1871 - } 1872 - }, 1873 - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { 1874 - "version": "7.6.3", 1875 - "dev": true, 1876 - "license": "ISC", 1877 - "bin": { 1878 - "semver": "bin/semver.js" 1879 - }, 1880 - "engines": { 1881 - "node": ">=10" 1882 - } 1883 - }, 1884 - "node_modules/@typescript-eslint/utils": { 1885 - "version": "8.21.0", 1886 - "dev": true, 1887 - "license": "MIT", 1888 - "dependencies": { 1889 - "@eslint-community/eslint-utils": "^4.4.0", 1890 - "@typescript-eslint/scope-manager": "8.21.0", 1891 - "@typescript-eslint/types": "8.21.0", 1892 - "@typescript-eslint/typescript-estree": "8.21.0" 1893 - }, 1894 - "engines": { 1895 - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 1896 - }, 1897 - "funding": { 1898 - "type": "opencollective", 1899 - "url": "https://opencollective.com/typescript-eslint" 1900 - }, 1901 - "peerDependencies": { 1902 - "eslint": "^8.57.0 || ^9.0.0", 1903 - "typescript": ">=4.8.4 <5.8.0" 1904 - } 1905 - }, 1906 - "node_modules/@typescript-eslint/visitor-keys": { 1907 - "version": "8.21.0", 1908 - "dev": true, 1909 - "license": "MIT", 1910 - "dependencies": { 1911 - "@typescript-eslint/types": "8.21.0", 1912 - "eslint-visitor-keys": "^4.2.0" 1913 - }, 1914 - "engines": { 1915 - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 1916 - }, 1917 - "funding": { 1918 - "type": "opencollective", 1919 - "url": "https://opencollective.com/typescript-eslint" 1920 - } 1921 - }, 1922 - "node_modules/@vitejs/plugin-react": { 1923 - "version": "4.3.4", 1924 - "dev": true, 1925 - "license": "MIT", 1926 - "dependencies": { 1927 - "@babel/core": "^7.26.0", 1928 - "@babel/plugin-transform-react-jsx-self": "^7.25.9", 1929 - "@babel/plugin-transform-react-jsx-source": "^7.25.9", 1930 - "@types/babel__core": "^7.20.5", 1931 - "react-refresh": "^0.14.2" 1932 - }, 1933 - "engines": { 1934 - "node": "^14.18.0 || >=16.0.0" 1935 - }, 1936 - "peerDependencies": { 1937 - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" 1938 - } 1939 - }, 1940 - "node_modules/acorn": { 1941 - "version": "8.14.0", 1942 - "dev": true, 1943 - "license": "MIT", 1944 - "bin": { 1945 - "acorn": "bin/acorn" 1946 - }, 1947 - "engines": { 1948 - "node": ">=0.4.0" 1949 - } 1950 - }, 1951 - "node_modules/acorn-jsx": { 1952 - "version": "5.3.2", 1953 - "dev": true, 1954 - "license": "MIT", 1955 - "peerDependencies": { 1956 - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" 1957 - } 1958 - }, 1959 - "node_modules/ajv": { 1960 - "version": "6.12.6", 1961 - "dev": true, 1962 - "license": "MIT", 1963 - "dependencies": { 1964 - "fast-deep-equal": "^3.1.1", 1965 - "fast-json-stable-stringify": "^2.0.0", 1966 - "json-schema-traverse": "^0.4.1", 1967 - "uri-js": "^4.2.2" 1968 - }, 1969 - "funding": { 1970 - "type": "github", 1971 - "url": "https://github.com/sponsors/epoberezkin" 1972 - } 1973 - }, 1974 - "node_modules/ansi-styles": { 1975 - "version": "4.3.0", 1976 - "dev": true, 1977 - "license": "MIT", 1978 - "dependencies": { 1979 - "color-convert": "^2.0.1" 1980 - }, 1981 - "engines": { 1982 - "node": ">=8" 1983 - }, 1984 - "funding": { 1985 - "url": "https://github.com/chalk/ansi-styles?sponsor=1" 1986 - } 1987 - }, 1988 - "node_modules/argparse": { 1989 - "version": "2.0.1", 1990 - "dev": true, 1991 - "license": "Python-2.0" 1992 - }, 1993 - "node_modules/aria-hidden": { 1994 - "version": "1.2.4", 1995 - "license": "MIT", 1996 - "dependencies": { 1997 - "tslib": "^2.0.0" 1998 - }, 1999 - "engines": { 2000 - "node": ">=10" 2001 - } 2002 - }, 2003 - "node_modules/asynckit": { 2004 - "version": "0.4.0", 2005 - "license": "MIT" 2006 - }, 2007 - "node_modules/axios": { 2008 - "version": "1.7.9", 2009 - "license": "MIT", 2010 - "dependencies": { 2011 - "follow-redirects": "^1.15.6", 2012 - "form-data": "^4.0.0", 2013 - "proxy-from-env": "^1.1.0" 2014 - } 2015 - }, 2016 - "node_modules/babel-plugin-macros": { 2017 - "version": "3.1.0", 2018 - "license": "MIT", 2019 - "dependencies": { 2020 - "@babel/runtime": "^7.12.5", 2021 - "cosmiconfig": "^7.0.0", 2022 - "resolve": "^1.19.0" 2023 - }, 2024 - "engines": { 2025 - "node": ">=10", 2026 - "npm": ">=6" 2027 - } 2028 - }, 2029 - "node_modules/balanced-match": { 2030 - "version": "1.0.2", 2031 - "dev": true, 2032 - "license": "MIT" 2033 - }, 2034 - "node_modules/brace-expansion": { 2035 - "version": "1.1.11", 2036 - "dev": true, 2037 - "license": "MIT", 2038 - "dependencies": { 2039 - "balanced-match": "^1.0.0", 2040 - "concat-map": "0.0.1" 2041 - } 2042 - }, 2043 - "node_modules/braces": { 2044 - "version": "3.0.3", 2045 - "dev": true, 2046 - "license": "MIT", 2047 - "dependencies": { 2048 - "fill-range": "^7.1.1" 2049 - }, 2050 - "engines": { 2051 - "node": ">=8" 2052 - } 2053 - }, 2054 - "node_modules/browserslist": { 2055 - "version": "4.24.4", 2056 - "dev": true, 2057 - "funding": [ 2058 - { 2059 - "type": "opencollective", 2060 - "url": "https://opencollective.com/browserslist" 2061 - }, 2062 - { 2063 - "type": "tidelift", 2064 - "url": "https://tidelift.com/funding/github/npm/browserslist" 2065 - }, 2066 - { 2067 - "type": "github", 2068 - "url": "https://github.com/sponsors/ai" 2069 - } 2070 - ], 2071 - "license": "MIT", 2072 - "dependencies": { 2073 - "caniuse-lite": "^1.0.30001688", 2074 - "electron-to-chromium": "^1.5.73", 2075 - "node-releases": "^2.0.19", 2076 - "update-browserslist-db": "^1.1.1" 2077 - }, 2078 - "bin": { 2079 - "browserslist": "cli.js" 2080 - }, 2081 - "engines": { 2082 - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" 2083 - } 2084 - }, 2085 - "node_modules/callsites": { 2086 - "version": "3.1.0", 2087 - "license": "MIT", 2088 - "engines": { 2089 - "node": ">=6" 2090 - } 2091 - }, 2092 - "node_modules/caniuse-lite": { 2093 - "version": "1.0.30001695", 2094 - "dev": true, 2095 - "funding": [ 2096 - { 2097 - "type": "opencollective", 2098 - "url": "https://opencollective.com/browserslist" 2099 - }, 2100 - { 2101 - "type": "tidelift", 2102 - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" 2103 - }, 2104 - { 2105 - "type": "github", 2106 - "url": "https://github.com/sponsors/ai" 2107 - } 2108 - ], 2109 - "license": "CC-BY-4.0" 2110 - }, 2111 - "node_modules/chalk": { 2112 - "version": "4.1.2", 2113 - "dev": true, 2114 - "license": "MIT", 2115 - "dependencies": { 2116 - "ansi-styles": "^4.1.0", 2117 - "supports-color": "^7.1.0" 2118 - }, 2119 - "engines": { 2120 - "node": ">=10" 2121 - }, 2122 - "funding": { 2123 - "url": "https://github.com/chalk/chalk?sponsor=1" 2124 - } 2125 - }, 2126 - "node_modules/class-variance-authority": { 2127 - "version": "0.7.1", 2128 - "license": "Apache-2.0", 2129 - "dependencies": { 2130 - "clsx": "^2.1.1" 2131 - }, 2132 - "funding": { 2133 - "url": "https://polar.sh/cva" 2134 - } 2135 - }, 2136 - "node_modules/clsx": { 2137 - "version": "2.1.1", 2138 - "license": "MIT", 2139 - "engines": { 2140 - "node": ">=6" 2141 - } 2142 - }, 2143 - "node_modules/color-convert": { 2144 - "version": "2.0.1", 2145 - "dev": true, 2146 - "license": "MIT", 2147 - "dependencies": { 2148 - "color-name": "~1.1.4" 2149 - }, 2150 - "engines": { 2151 - "node": ">=7.0.0" 2152 - } 2153 - }, 2154 - "node_modules/color-name": { 2155 - "version": "1.1.4", 2156 - "dev": true, 2157 - "license": "MIT" 2158 - }, 2159 - "node_modules/combined-stream": { 2160 - "version": "1.0.8", 2161 - "license": "MIT", 2162 - "dependencies": { 2163 - "delayed-stream": "~1.0.0" 2164 - }, 2165 - "engines": { 2166 - "node": ">= 0.8" 2167 - } 2168 - }, 2169 - "node_modules/concat-map": { 2170 - "version": "0.0.1", 2171 - "dev": true, 2172 - "license": "MIT" 2173 - }, 2174 - "node_modules/convert-source-map": { 2175 - "version": "2.0.0", 2176 - "dev": true, 2177 - "license": "MIT" 2178 - }, 2179 - "node_modules/cosmiconfig": { 2180 - "version": "7.1.0", 2181 - "license": "MIT", 2182 - "dependencies": { 2183 - "@types/parse-json": "^4.0.0", 2184 - "import-fresh": "^3.2.1", 2185 - "parse-json": "^5.0.0", 2186 - "path-type": "^4.0.0", 2187 - "yaml": "^1.10.0" 2188 - }, 2189 - "engines": { 2190 - "node": ">=10" 2191 - } 2192 - }, 2193 - "node_modules/cosmiconfig/node_modules/yaml": { 2194 - "version": "1.10.2", 2195 - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", 2196 - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", 2197 - "license": "ISC", 2198 - "engines": { 2199 - "node": ">= 6" 2200 - } 2201 - }, 2202 - "node_modules/cross-spawn": { 2203 - "version": "7.0.6", 2204 - "dev": true, 2205 - "license": "MIT", 2206 - "dependencies": { 2207 - "path-key": "^3.1.0", 2208 - "shebang-command": "^2.0.0", 2209 - "which": "^2.0.1" 2210 - }, 2211 - "engines": { 2212 - "node": ">= 8" 2213 - } 2214 - }, 2215 - "node_modules/csstype": { 2216 - "version": "3.1.3", 2217 - "license": "MIT" 2218 - }, 2219 - "node_modules/d3-array": { 2220 - "version": "3.2.4", 2221 - "license": "ISC", 2222 - "dependencies": { 2223 - "internmap": "1 - 2" 2224 - }, 2225 - "engines": { 2226 - "node": ">=12" 2227 - } 2228 - }, 2229 - "node_modules/d3-color": { 2230 - "version": "3.1.0", 2231 - "license": "ISC", 2232 - "engines": { 2233 - "node": ">=12" 2234 - } 2235 - }, 2236 - "node_modules/d3-ease": { 2237 - "version": "3.0.1", 2238 - "license": "BSD-3-Clause", 2239 - "engines": { 2240 - "node": ">=12" 2241 - } 2242 - }, 2243 - "node_modules/d3-format": { 2244 - "version": "3.1.0", 2245 - "license": "ISC", 2246 - "engines": { 2247 - "node": ">=12" 2248 - } 2249 - }, 2250 - "node_modules/d3-interpolate": { 2251 - "version": "3.0.1", 2252 - "license": "ISC", 2253 - "dependencies": { 2254 - "d3-color": "1 - 3" 2255 - }, 2256 - "engines": { 2257 - "node": ">=12" 2258 - } 2259 - }, 2260 - "node_modules/d3-path": { 2261 - "version": "3.1.0", 2262 - "license": "ISC", 2263 - "engines": { 2264 - "node": ">=12" 2265 - } 2266 - }, 2267 - "node_modules/d3-scale": { 2268 - "version": "4.0.2", 2269 - "license": "ISC", 2270 - "dependencies": { 2271 - "d3-array": "2.10.0 - 3", 2272 - "d3-format": "1 - 3", 2273 - "d3-interpolate": "1.2.0 - 3", 2274 - "d3-time": "2.1.1 - 3", 2275 - "d3-time-format": "2 - 4" 2276 - }, 2277 - "engines": { 2278 - "node": ">=12" 2279 - } 2280 - }, 2281 - "node_modules/d3-shape": { 2282 - "version": "3.2.0", 2283 - "license": "ISC", 2284 - "dependencies": { 2285 - "d3-path": "^3.1.0" 2286 - }, 2287 - "engines": { 2288 - "node": ">=12" 2289 - } 2290 - }, 2291 - "node_modules/d3-time": { 2292 - "version": "3.1.0", 2293 - "license": "ISC", 2294 - "dependencies": { 2295 - "d3-array": "2 - 3" 2296 - }, 2297 - "engines": { 2298 - "node": ">=12" 2299 - } 2300 - }, 2301 - "node_modules/d3-time-format": { 2302 - "version": "4.1.0", 2303 - "license": "ISC", 2304 - "dependencies": { 2305 - "d3-time": "1 - 3" 2306 - }, 2307 - "engines": { 2308 - "node": ">=12" 2309 - } 2310 - }, 2311 - "node_modules/d3-timer": { 2312 - "version": "3.0.1", 2313 - "license": "ISC", 2314 - "engines": { 2315 - "node": ">=12" 2316 - } 2317 - }, 2318 - "node_modules/debug": { 2319 - "version": "4.4.0", 2320 - "license": "MIT", 2321 - "dependencies": { 2322 - "ms": "^2.1.3" 2323 - }, 2324 - "engines": { 2325 - "node": ">=6.0" 2326 - }, 2327 - "peerDependenciesMeta": { 2328 - "supports-color": { 2329 - "optional": true 2330 - } 2331 - } 2332 - }, 2333 - "node_modules/decimal.js-light": { 2334 - "version": "2.5.1", 2335 - "license": "MIT" 2336 - }, 2337 - "node_modules/deep-is": { 2338 - "version": "0.1.4", 2339 - "dev": true, 2340 - "license": "MIT" 2341 - }, 2342 - "node_modules/delayed-stream": { 2343 - "version": "1.0.0", 2344 - "license": "MIT", 2345 - "engines": { 2346 - "node": ">=0.4.0" 2347 - } 2348 - }, 2349 - "node_modules/detect-libc": { 2350 - "version": "1.0.3", 2351 - "license": "Apache-2.0", 2352 - "bin": { 2353 - "detect-libc": "bin/detect-libc.js" 2354 - }, 2355 - "engines": { 2356 - "node": ">=0.10" 2357 - } 2358 - }, 2359 - "node_modules/detect-node-es": { 2360 - "version": "1.1.0", 2361 - "license": "MIT" 2362 - }, 2363 - "node_modules/dom-helpers": { 2364 - "version": "5.2.1", 2365 - "license": "MIT", 2366 - "dependencies": { 2367 - "@babel/runtime": "^7.8.7", 2368 - "csstype": "^3.0.2" 2369 - } 2370 - }, 2371 - "node_modules/electron-to-chromium": { 2372 - "version": "1.5.88", 2373 - "dev": true, 2374 - "license": "ISC" 2375 - }, 2376 - "node_modules/enhanced-resolve": { 2377 - "version": "5.18.0", 2378 - "license": "MIT", 2379 - "dependencies": { 2380 - "graceful-fs": "^4.2.4", 2381 - "tapable": "^2.2.0" 2382 - }, 2383 - "engines": { 2384 - "node": ">=10.13.0" 2385 - } 2386 - }, 2387 - "node_modules/error-ex": { 2388 - "version": "1.3.2", 2389 - "license": "MIT", 2390 - "dependencies": { 2391 - "is-arrayish": "^0.2.1" 2392 - } 2393 - }, 2394 - "node_modules/esbuild": { 2395 - "version": "0.24.2", 2396 - "hasInstallScript": true, 2397 - "license": "MIT", 2398 - "bin": { 2399 - "esbuild": "bin/esbuild" 2400 - }, 2401 - "engines": { 2402 - "node": ">=18" 2403 - }, 2404 - "optionalDependencies": { 2405 - "@esbuild/aix-ppc64": "0.24.2", 2406 - "@esbuild/android-arm": "0.24.2", 2407 - "@esbuild/android-arm64": "0.24.2", 2408 - "@esbuild/android-x64": "0.24.2", 2409 - "@esbuild/darwin-arm64": "0.24.2", 2410 - "@esbuild/darwin-x64": "0.24.2", 2411 - "@esbuild/freebsd-arm64": "0.24.2", 2412 - "@esbuild/freebsd-x64": "0.24.2", 2413 - "@esbuild/linux-arm": "0.24.2", 2414 - "@esbuild/linux-arm64": "0.24.2", 2415 - "@esbuild/linux-ia32": "0.24.2", 2416 - "@esbuild/linux-loong64": "0.24.2", 2417 - "@esbuild/linux-mips64el": "0.24.2", 2418 - "@esbuild/linux-ppc64": "0.24.2", 2419 - "@esbuild/linux-riscv64": "0.24.2", 2420 - "@esbuild/linux-s390x": "0.24.2", 2421 - "@esbuild/linux-x64": "0.24.2", 2422 - "@esbuild/netbsd-arm64": "0.24.2", 2423 - "@esbuild/netbsd-x64": "0.24.2", 2424 - "@esbuild/openbsd-arm64": "0.24.2", 2425 - "@esbuild/openbsd-x64": "0.24.2", 2426 - "@esbuild/sunos-x64": "0.24.2", 2427 - "@esbuild/win32-arm64": "0.24.2", 2428 - "@esbuild/win32-ia32": "0.24.2", 2429 - "@esbuild/win32-x64": "0.24.2" 2430 - } 2431 - }, 2432 - "node_modules/escalade": { 2433 - "version": "3.2.0", 2434 - "dev": true, 2435 - "license": "MIT", 2436 - "engines": { 2437 - "node": ">=6" 2438 - } 2439 - }, 2440 - "node_modules/escape-string-regexp": { 2441 - "version": "4.0.0", 2442 - "license": "MIT", 2443 - "engines": { 2444 - "node": ">=10" 2445 - }, 2446 - "funding": { 2447 - "url": "https://github.com/sponsors/sindresorhus" 2448 - } 2449 - }, 2450 - "node_modules/eslint": { 2451 - "version": "9.19.0", 2452 - "dev": true, 2453 - "license": "MIT", 2454 - "dependencies": { 2455 - "@eslint-community/eslint-utils": "^4.2.0", 2456 - "@eslint-community/regexpp": "^4.12.1", 2457 - "@eslint/config-array": "^0.19.0", 2458 - "@eslint/core": "^0.10.0", 2459 - "@eslint/eslintrc": "^3.2.0", 2460 - "@eslint/js": "9.19.0", 2461 - "@eslint/plugin-kit": "^0.2.5", 2462 - "@humanfs/node": "^0.16.6", 2463 - "@humanwhocodes/module-importer": "^1.0.1", 2464 - "@humanwhocodes/retry": "^0.4.1", 2465 - "@types/estree": "^1.0.6", 2466 - "@types/json-schema": "^7.0.15", 2467 - "ajv": "^6.12.4", 2468 - "chalk": "^4.0.0", 2469 - "cross-spawn": "^7.0.6", 2470 - "debug": "^4.3.2", 2471 - "escape-string-regexp": "^4.0.0", 2472 - "eslint-scope": "^8.2.0", 2473 - "eslint-visitor-keys": "^4.2.0", 2474 - "espree": "^10.3.0", 2475 - "esquery": "^1.5.0", 2476 - "esutils": "^2.0.2", 2477 - "fast-deep-equal": "^3.1.3", 2478 - "file-entry-cache": "^8.0.0", 2479 - "find-up": "^5.0.0", 2480 - "glob-parent": "^6.0.2", 2481 - "ignore": "^5.2.0", 2482 - "imurmurhash": "^0.1.4", 2483 - "is-glob": "^4.0.0", 2484 - "json-stable-stringify-without-jsonify": "^1.0.1", 2485 - "lodash.merge": "^4.6.2", 2486 - "minimatch": "^3.1.2", 2487 - "natural-compare": "^1.4.0", 2488 - "optionator": "^0.9.3" 2489 - }, 2490 - "bin": { 2491 - "eslint": "bin/eslint.js" 2492 - }, 2493 - "engines": { 2494 - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 2495 - }, 2496 - "funding": { 2497 - "url": "https://eslint.org/donate" 2498 - }, 2499 - "peerDependencies": { 2500 - "jiti": "*" 2501 - }, 2502 - "peerDependenciesMeta": { 2503 - "jiti": { 2504 - "optional": true 2505 - } 2506 - } 2507 - }, 2508 - "node_modules/eslint-plugin-react-hooks": { 2509 - "version": "5.1.0", 2510 - "dev": true, 2511 - "license": "MIT", 2512 - "engines": { 2513 - "node": ">=10" 2514 - }, 2515 - "peerDependencies": { 2516 - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" 2517 - } 2518 - }, 2519 - "node_modules/eslint-plugin-react-refresh": { 2520 - "version": "0.4.18", 2521 - "dev": true, 2522 - "license": "MIT", 2523 - "peerDependencies": { 2524 - "eslint": ">=8.40" 2525 - } 2526 - }, 2527 - "node_modules/eslint-scope": { 2528 - "version": "8.2.0", 2529 - "dev": true, 2530 - "license": "BSD-2-Clause", 2531 - "dependencies": { 2532 - "esrecurse": "^4.3.0", 2533 - "estraverse": "^5.2.0" 2534 - }, 2535 - "engines": { 2536 - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 2537 - }, 2538 - "funding": { 2539 - "url": "https://opencollective.com/eslint" 2540 - } 2541 - }, 2542 - "node_modules/eslint-visitor-keys": { 2543 - "version": "4.2.0", 2544 - "dev": true, 2545 - "license": "Apache-2.0", 2546 - "engines": { 2547 - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 2548 - }, 2549 - "funding": { 2550 - "url": "https://opencollective.com/eslint" 2551 - } 2552 - }, 2553 - "node_modules/espree": { 2554 - "version": "10.3.0", 2555 - "dev": true, 2556 - "license": "BSD-2-Clause", 2557 - "dependencies": { 2558 - "acorn": "^8.14.0", 2559 - "acorn-jsx": "^5.3.2", 2560 - "eslint-visitor-keys": "^4.2.0" 2561 - }, 2562 - "engines": { 2563 - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 2564 - }, 2565 - "funding": { 2566 - "url": "https://opencollective.com/eslint" 2567 - } 2568 - }, 2569 - "node_modules/esquery": { 2570 - "version": "1.6.0", 2571 - "dev": true, 2572 - "license": "BSD-3-Clause", 2573 - "dependencies": { 2574 - "estraverse": "^5.1.0" 2575 - }, 2576 - "engines": { 2577 - "node": ">=0.10" 2578 - } 2579 - }, 2580 - "node_modules/esrecurse": { 2581 - "version": "4.3.0", 2582 - "dev": true, 2583 - "license": "BSD-2-Clause", 2584 - "dependencies": { 2585 - "estraverse": "^5.2.0" 2586 - }, 2587 - "engines": { 2588 - "node": ">=4.0" 2589 - } 2590 - }, 2591 - "node_modules/estraverse": { 2592 - "version": "5.3.0", 2593 - "dev": true, 2594 - "license": "BSD-2-Clause", 2595 - "engines": { 2596 - "node": ">=4.0" 2597 - } 2598 - }, 2599 - "node_modules/esutils": { 2600 - "version": "2.0.3", 2601 - "dev": true, 2602 - "license": "BSD-2-Clause", 2603 - "engines": { 2604 - "node": ">=0.10.0" 2605 - } 2606 - }, 2607 - "node_modules/eventemitter3": { 2608 - "version": "4.0.7", 2609 - "license": "MIT" 2610 - }, 2611 - "node_modules/fast-deep-equal": { 2612 - "version": "3.1.3", 2613 - "license": "MIT" 2614 - }, 2615 - "node_modules/fast-equals": { 2616 - "version": "5.2.2", 2617 - "license": "MIT", 2618 - "engines": { 2619 - "node": ">=6.0.0" 2620 - } 2621 - }, 2622 - "node_modules/fast-glob": { 2623 - "version": "3.3.3", 2624 - "dev": true, 2625 - "license": "MIT", 2626 - "dependencies": { 2627 - "@nodelib/fs.stat": "^2.0.2", 2628 - "@nodelib/fs.walk": "^1.2.3", 2629 - "glob-parent": "^5.1.2", 2630 - "merge2": "^1.3.0", 2631 - "micromatch": "^4.0.8" 2632 - }, 2633 - "engines": { 2634 - "node": ">=8.6.0" 2635 - } 2636 - }, 2637 - "node_modules/fast-glob/node_modules/glob-parent": { 2638 - "version": "5.1.2", 2639 - "dev": true, 2640 - "license": "ISC", 2641 - "dependencies": { 2642 - "is-glob": "^4.0.1" 2643 - }, 2644 - "engines": { 2645 - "node": ">= 6" 2646 - } 2647 - }, 2648 - "node_modules/fast-json-stable-stringify": { 2649 - "version": "2.1.0", 2650 - "dev": true, 2651 - "license": "MIT" 2652 - }, 2653 - "node_modules/fast-levenshtein": { 2654 - "version": "2.0.6", 2655 - "dev": true, 2656 - "license": "MIT" 2657 - }, 2658 - "node_modules/fastq": { 2659 - "version": "1.18.0", 2660 - "dev": true, 2661 - "license": "ISC", 2662 - "dependencies": { 2663 - "reusify": "^1.0.4" 2664 - } 2665 - }, 2666 - "node_modules/file-entry-cache": { 2667 - "version": "8.0.0", 2668 - "dev": true, 2669 - "license": "MIT", 2670 - "dependencies": { 2671 - "flat-cache": "^4.0.0" 2672 - }, 2673 - "engines": { 2674 - "node": ">=16.0.0" 2675 - } 2676 - }, 2677 - "node_modules/fill-range": { 2678 - "version": "7.1.1", 2679 - "dev": true, 2680 - "license": "MIT", 2681 - "dependencies": { 2682 - "to-regex-range": "^5.0.1" 2683 - }, 2684 - "engines": { 2685 - "node": ">=8" 2686 - } 2687 - }, 2688 - "node_modules/find-root": { 2689 - "version": "1.1.0", 2690 - "license": "MIT" 2691 - }, 2692 - "node_modules/find-up": { 2693 - "version": "5.0.0", 2694 - "dev": true, 2695 - "license": "MIT", 2696 - "dependencies": { 2697 - "locate-path": "^6.0.0", 2698 - "path-exists": "^4.0.0" 2699 - }, 2700 - "engines": { 2701 - "node": ">=10" 2702 - }, 2703 - "funding": { 2704 - "url": "https://github.com/sponsors/sindresorhus" 2705 - } 2706 - }, 2707 - "node_modules/flat-cache": { 2708 - "version": "4.0.1", 2709 - "dev": true, 2710 - "license": "MIT", 2711 - "dependencies": { 2712 - "flatted": "^3.2.9", 2713 - "keyv": "^4.5.4" 2714 - }, 2715 - "engines": { 2716 - "node": ">=16" 2717 - } 2718 - }, 2719 - "node_modules/flatted": { 2720 - "version": "3.3.2", 2721 - "dev": true, 2722 - "license": "ISC" 2723 - }, 2724 - "node_modules/follow-redirects": { 2725 - "version": "1.15.9", 2726 - "funding": [ 2727 - { 2728 - "type": "individual", 2729 - "url": "https://github.com/sponsors/RubenVerborgh" 2730 - } 2731 - ], 2732 - "license": "MIT", 2733 - "engines": { 2734 - "node": ">=4.0" 2735 - }, 2736 - "peerDependenciesMeta": { 2737 - "debug": { 2738 - "optional": true 2739 - } 2740 - } 2741 - }, 2742 - "node_modules/form-data": { 2743 - "version": "4.0.1", 2744 - "license": "MIT", 2745 - "dependencies": { 2746 - "asynckit": "^0.4.0", 2747 - "combined-stream": "^1.0.8", 2748 - "mime-types": "^2.1.12" 2749 - }, 2750 - "engines": { 2751 - "node": ">= 6" 2752 - } 2753 - }, 2754 - "node_modules/fsevents": { 2755 - "version": "2.3.3", 2756 - "license": "MIT", 2757 - "optional": true, 2758 - "os": [ 2759 - "darwin" 2760 - ], 2761 - "engines": { 2762 - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 2763 - } 2764 - }, 2765 - "node_modules/function-bind": { 2766 - "version": "1.1.2", 2767 - "license": "MIT", 2768 - "funding": { 2769 - "url": "https://github.com/sponsors/ljharb" 2770 - } 2771 - }, 2772 - "node_modules/gensync": { 2773 - "version": "1.0.0-beta.2", 2774 - "dev": true, 2775 - "license": "MIT", 2776 - "engines": { 2777 - "node": ">=6.9.0" 2778 - } 2779 - }, 2780 - "node_modules/get-nonce": { 2781 - "version": "1.0.1", 2782 - "license": "MIT", 2783 - "engines": { 2784 - "node": ">=6" 2785 - } 2786 - }, 2787 - "node_modules/glob-parent": { 2788 - "version": "6.0.2", 2789 - "dev": true, 2790 - "license": "ISC", 2791 - "dependencies": { 2792 - "is-glob": "^4.0.3" 2793 - }, 2794 - "engines": { 2795 - "node": ">=10.13.0" 2796 - } 2797 - }, 2798 - "node_modules/globals": { 2799 - "version": "15.14.0", 2800 - "dev": true, 2801 - "license": "MIT", 2802 - "engines": { 2803 - "node": ">=18" 2804 - }, 2805 - "funding": { 2806 - "url": "https://github.com/sponsors/sindresorhus" 2807 - } 2808 - }, 2809 - "node_modules/graceful-fs": { 2810 - "version": "4.2.11", 2811 - "license": "ISC" 2812 - }, 2813 - "node_modules/graphemer": { 2814 - "version": "1.4.0", 2815 - "dev": true, 2816 - "license": "MIT" 2817 - }, 2818 - "node_modules/has-flag": { 2819 - "version": "4.0.0", 2820 - "dev": true, 2821 - "license": "MIT", 2822 - "engines": { 2823 - "node": ">=8" 2824 - } 2825 - }, 2826 - "node_modules/hasown": { 2827 - "version": "2.0.2", 2828 - "license": "MIT", 2829 - "dependencies": { 2830 - "function-bind": "^1.1.2" 2831 - }, 2832 - "engines": { 2833 - "node": ">= 0.4" 2834 - } 2835 - }, 2836 - "node_modules/hoist-non-react-statics": { 2837 - "version": "3.3.2", 2838 - "license": "BSD-3-Clause", 2839 - "dependencies": { 2840 - "react-is": "^16.7.0" 2841 - } 2842 - }, 2843 - "node_modules/hoist-non-react-statics/node_modules/react-is": { 2844 - "version": "16.13.1", 2845 - "license": "MIT" 2846 - }, 2847 - "node_modules/ignore": { 2848 - "version": "5.3.2", 2849 - "dev": true, 2850 - "license": "MIT", 2851 - "engines": { 2852 - "node": ">= 4" 2853 - } 2854 - }, 2855 - "node_modules/import-fresh": { 2856 - "version": "3.3.0", 2857 - "license": "MIT", 2858 - "dependencies": { 2859 - "parent-module": "^1.0.0", 2860 - "resolve-from": "^4.0.0" 2861 - }, 2862 - "engines": { 2863 - "node": ">=6" 2864 - }, 2865 - "funding": { 2866 - "url": "https://github.com/sponsors/sindresorhus" 2867 - } 2868 - }, 2869 - "node_modules/imurmurhash": { 2870 - "version": "0.1.4", 2871 - "dev": true, 2872 - "license": "MIT", 2873 - "engines": { 2874 - "node": ">=0.8.19" 2875 - } 2876 - }, 2877 - "node_modules/internmap": { 2878 - "version": "2.0.3", 2879 - "license": "ISC", 2880 - "engines": { 2881 - "node": ">=12" 2882 - } 2883 - }, 2884 - "node_modules/is-arrayish": { 2885 - "version": "0.2.1", 2886 - "license": "MIT" 2887 - }, 2888 - "node_modules/is-core-module": { 2889 - "version": "2.16.1", 2890 - "license": "MIT", 2891 - "dependencies": { 2892 - "hasown": "^2.0.2" 2893 - }, 2894 - "engines": { 2895 - "node": ">= 0.4" 2896 - }, 2897 - "funding": { 2898 - "url": "https://github.com/sponsors/ljharb" 2899 - } 2900 - }, 2901 - "node_modules/is-extglob": { 2902 - "version": "2.1.1", 2903 - "dev": true, 2904 - "license": "MIT", 2905 - "engines": { 2906 - "node": ">=0.10.0" 2907 - } 2908 - }, 2909 - "node_modules/is-glob": { 2910 - "version": "4.0.3", 2911 - "dev": true, 2912 - "license": "MIT", 2913 - "dependencies": { 2914 - "is-extglob": "^2.1.1" 2915 - }, 2916 - "engines": { 2917 - "node": ">=0.10.0" 2918 - } 2919 - }, 2920 - "node_modules/is-number": { 2921 - "version": "7.0.0", 2922 - "dev": true, 2923 - "license": "MIT", 2924 - "engines": { 2925 - "node": ">=0.12.0" 2926 - } 2927 - }, 2928 - "node_modules/isexe": { 2929 - "version": "2.0.0", 2930 - "dev": true, 2931 - "license": "ISC" 2932 - }, 2933 - "node_modules/jiti": { 2934 - "version": "2.4.2", 2935 - "license": "MIT", 2936 - "bin": { 2937 - "jiti": "lib/jiti-cli.mjs" 2938 - } 2939 - }, 2940 - "node_modules/js-tokens": { 2941 - "version": "4.0.0", 2942 - "license": "MIT" 2943 - }, 2944 - "node_modules/js-yaml": { 2945 - "version": "4.1.0", 2946 - "dev": true, 2947 - "license": "MIT", 2948 - "dependencies": { 2949 - "argparse": "^2.0.1" 2950 - }, 2951 - "bin": { 2952 - "js-yaml": "bin/js-yaml.js" 2953 - } 2954 - }, 2955 - "node_modules/jsesc": { 2956 - "version": "3.1.0", 2957 - "license": "MIT", 2958 - "bin": { 2959 - "jsesc": "bin/jsesc" 2960 - }, 2961 - "engines": { 2962 - "node": ">=6" 2963 - } 2964 - }, 2965 - "node_modules/json-buffer": { 2966 - "version": "3.0.1", 2967 - "dev": true, 2968 - "license": "MIT" 2969 - }, 2970 - "node_modules/json-parse-even-better-errors": { 2971 - "version": "2.3.1", 2972 - "license": "MIT" 2973 - }, 2974 - "node_modules/json-schema-traverse": { 2975 - "version": "0.4.1", 2976 - "dev": true, 2977 - "license": "MIT" 2978 - }, 2979 - "node_modules/json-stable-stringify-without-jsonify": { 2980 - "version": "1.0.1", 2981 - "dev": true, 2982 - "license": "MIT" 2983 - }, 2984 - "node_modules/json5": { 2985 - "version": "2.2.3", 2986 - "dev": true, 2987 - "license": "MIT", 2988 - "bin": { 2989 - "json5": "lib/cli.js" 2990 - }, 2991 - "engines": { 2992 - "node": ">=6" 2993 - } 2994 - }, 2995 - "node_modules/keyv": { 2996 - "version": "4.5.4", 2997 - "dev": true, 2998 - "license": "MIT", 2999 - "dependencies": { 3000 - "json-buffer": "3.0.1" 3001 - } 3002 - }, 3003 - "node_modules/klona": { 3004 - "version": "2.0.6", 3005 - "license": "MIT", 3006 - "engines": { 3007 - "node": ">= 8" 3008 - } 3009 - }, 3010 - "node_modules/levn": { 3011 - "version": "0.4.1", 3012 - "dev": true, 3013 - "license": "MIT", 3014 - "dependencies": { 3015 - "prelude-ls": "^1.2.1", 3016 - "type-check": "~0.4.0" 3017 - }, 3018 - "engines": { 3019 - "node": ">= 0.8.0" 3020 - } 3021 - }, 3022 - "node_modules/lightningcss": { 3023 - "version": "1.29.1", 3024 - "license": "MPL-2.0", 3025 - "dependencies": { 3026 - "detect-libc": "^1.0.3" 3027 - }, 3028 - "engines": { 3029 - "node": ">= 12.0.0" 3030 - }, 3031 - "funding": { 3032 - "type": "opencollective", 3033 - "url": "https://opencollective.com/parcel" 3034 - }, 3035 - "optionalDependencies": { 3036 - "lightningcss-darwin-arm64": "1.29.1", 3037 - "lightningcss-darwin-x64": "1.29.1", 3038 - "lightningcss-freebsd-x64": "1.29.1", 3039 - "lightningcss-linux-arm-gnueabihf": "1.29.1", 3040 - "lightningcss-linux-arm64-gnu": "1.29.1", 3041 - "lightningcss-linux-arm64-musl": "1.29.1", 3042 - "lightningcss-linux-x64-gnu": "1.29.1", 3043 - "lightningcss-linux-x64-musl": "1.29.1", 3044 - "lightningcss-win32-arm64-msvc": "1.29.1", 3045 - "lightningcss-win32-x64-msvc": "1.29.1" 3046 - } 3047 - }, 3048 - "node_modules/lightningcss-darwin-arm64": { 3049 - "version": "1.29.1", 3050 - "cpu": [ 3051 - "arm64" 3052 - ], 3053 - "license": "MPL-2.0", 3054 - "optional": true, 3055 - "os": [ 3056 - "darwin" 3057 - ], 3058 - "engines": { 3059 - "node": ">= 12.0.0" 3060 - }, 3061 - "funding": { 3062 - "type": "opencollective", 3063 - "url": "https://opencollective.com/parcel" 3064 - } 3065 - }, 3066 - "node_modules/lines-and-columns": { 3067 - "version": "1.2.4", 3068 - "license": "MIT" 3069 - }, 3070 - "node_modules/locate-path": { 3071 - "version": "6.0.0", 3072 - "dev": true, 3073 - "license": "MIT", 3074 - "dependencies": { 3075 - "p-locate": "^5.0.0" 3076 - }, 3077 - "engines": { 3078 - "node": ">=10" 3079 - }, 3080 - "funding": { 3081 - "url": "https://github.com/sponsors/sindresorhus" 3082 - } 3083 - }, 3084 - "node_modules/lodash": { 3085 - "version": "4.17.21", 3086 - "license": "MIT" 3087 - }, 3088 - "node_modules/lodash.merge": { 3089 - "version": "4.6.2", 3090 - "dev": true, 3091 - "license": "MIT" 3092 - }, 3093 - "node_modules/loose-envify": { 3094 - "version": "1.4.0", 3095 - "license": "MIT", 3096 - "dependencies": { 3097 - "js-tokens": "^3.0.0 || ^4.0.0" 3098 - }, 3099 - "bin": { 3100 - "loose-envify": "cli.js" 3101 - } 3102 - }, 3103 - "node_modules/lru-cache": { 3104 - "version": "5.1.1", 3105 - "dev": true, 3106 - "license": "ISC", 3107 - "dependencies": { 3108 - "yallist": "^3.0.2" 3109 - } 3110 - }, 3111 - "node_modules/lucide-react": { 3112 - "version": "0.474.0", 3113 - "license": "ISC", 3114 - "peerDependencies": { 3115 - "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" 3116 - } 3117 - }, 3118 - "node_modules/merge2": { 3119 - "version": "1.4.1", 3120 - "dev": true, 3121 - "license": "MIT", 3122 - "engines": { 3123 - "node": ">= 8" 3124 - } 3125 - }, 3126 - "node_modules/micromatch": { 3127 - "version": "4.0.8", 3128 - "dev": true, 3129 - "license": "MIT", 3130 - "dependencies": { 3131 - "braces": "^3.0.3", 3132 - "picomatch": "^2.3.1" 3133 - }, 3134 - "engines": { 3135 - "node": ">=8.6" 3136 - } 3137 - }, 3138 - "node_modules/mime-db": { 3139 - "version": "1.52.0", 3140 - "license": "MIT", 3141 - "engines": { 3142 - "node": ">= 0.6" 3143 - } 3144 - }, 3145 - "node_modules/mime-types": { 3146 - "version": "2.1.35", 3147 - "license": "MIT", 3148 - "dependencies": { 3149 - "mime-db": "1.52.0" 3150 - }, 3151 - "engines": { 3152 - "node": ">= 0.6" 3153 - } 3154 - }, 3155 - "node_modules/minimatch": { 3156 - "version": "3.1.2", 3157 - "dev": true, 3158 - "license": "ISC", 3159 - "dependencies": { 3160 - "brace-expansion": "^1.1.7" 3161 - }, 3162 - "engines": { 3163 - "node": "*" 3164 - } 3165 - }, 3166 - "node_modules/ms": { 3167 - "version": "2.1.3", 3168 - "license": "MIT" 3169 - }, 3170 - "node_modules/nanoid": { 3171 - "version": "3.3.8", 3172 - "funding": [ 3173 - { 3174 - "type": "github", 3175 - "url": "https://github.com/sponsors/ai" 3176 - } 3177 - ], 3178 - "license": "MIT", 3179 - "bin": { 3180 - "nanoid": "bin/nanoid.cjs" 3181 - }, 3182 - "engines": { 3183 - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 3184 - } 3185 - }, 3186 - "node_modules/natural-compare": { 3187 - "version": "1.4.0", 3188 - "dev": true, 3189 - "license": "MIT" 3190 - }, 3191 - "node_modules/node-releases": { 3192 - "version": "2.0.19", 3193 - "dev": true, 3194 - "license": "MIT" 3195 - }, 3196 - "node_modules/object-assign": { 3197 - "version": "4.1.1", 3198 - "license": "MIT", 3199 - "engines": { 3200 - "node": ">=0.10.0" 3201 - } 3202 - }, 3203 - "node_modules/optionator": { 3204 - "version": "0.9.4", 3205 - "dev": true, 3206 - "license": "MIT", 3207 - "dependencies": { 3208 - "deep-is": "^0.1.3", 3209 - "fast-levenshtein": "^2.0.6", 3210 - "levn": "^0.4.1", 3211 - "prelude-ls": "^1.2.1", 3212 - "type-check": "^0.4.0", 3213 - "word-wrap": "^1.2.5" 3214 - }, 3215 - "engines": { 3216 - "node": ">= 0.8.0" 3217 - } 3218 - }, 3219 - "node_modules/p-limit": { 3220 - "version": "3.1.0", 3221 - "dev": true, 3222 - "license": "MIT", 3223 - "dependencies": { 3224 - "yocto-queue": "^0.1.0" 3225 - }, 3226 - "engines": { 3227 - "node": ">=10" 3228 - }, 3229 - "funding": { 3230 - "url": "https://github.com/sponsors/sindresorhus" 3231 - } 3232 - }, 3233 - "node_modules/p-locate": { 3234 - "version": "5.0.0", 3235 - "dev": true, 3236 - "license": "MIT", 3237 - "dependencies": { 3238 - "p-limit": "^3.0.2" 3239 - }, 3240 - "engines": { 3241 - "node": ">=10" 3242 - }, 3243 - "funding": { 3244 - "url": "https://github.com/sponsors/sindresorhus" 3245 - } 3246 - }, 3247 - "node_modules/parent-module": { 3248 - "version": "1.0.1", 3249 - "license": "MIT", 3250 - "dependencies": { 3251 - "callsites": "^3.0.0" 3252 - }, 3253 - "engines": { 3254 - "node": ">=6" 3255 - } 3256 - }, 3257 - "node_modules/parse-json": { 3258 - "version": "5.2.0", 3259 - "license": "MIT", 3260 - "dependencies": { 3261 - "@babel/code-frame": "^7.0.0", 3262 - "error-ex": "^1.3.1", 3263 - "json-parse-even-better-errors": "^2.3.0", 3264 - "lines-and-columns": "^1.1.6" 3265 - }, 3266 - "engines": { 3267 - "node": ">=8" 3268 - }, 3269 - "funding": { 3270 - "url": "https://github.com/sponsors/sindresorhus" 3271 - } 3272 - }, 3273 - "node_modules/path-exists": { 3274 - "version": "4.0.0", 3275 - "dev": true, 3276 - "license": "MIT", 3277 - "engines": { 3278 - "node": ">=8" 3279 - } 3280 - }, 3281 - "node_modules/path-key": { 3282 - "version": "3.1.1", 3283 - "dev": true, 3284 - "license": "MIT", 3285 - "engines": { 3286 - "node": ">=8" 3287 - } 3288 - }, 3289 - "node_modules/path-parse": { 3290 - "version": "1.0.7", 3291 - "license": "MIT" 3292 - }, 3293 - "node_modules/path-type": { 3294 - "version": "4.0.0", 3295 - "license": "MIT", 3296 - "engines": { 3297 - "node": ">=8" 3298 - } 3299 - }, 3300 - "node_modules/picocolors": { 3301 - "version": "1.1.1", 3302 - "license": "ISC" 3303 - }, 3304 - "node_modules/picomatch": { 3305 - "version": "2.3.1", 3306 - "dev": true, 3307 - "license": "MIT", 3308 - "engines": { 3309 - "node": ">=8.6" 3310 - }, 3311 - "funding": { 3312 - "url": "https://github.com/sponsors/jonschlinkert" 3313 - } 3314 - }, 3315 - "node_modules/postcss": { 3316 - "version": "8.5.1", 3317 - "funding": [ 3318 - { 3319 - "type": "opencollective", 3320 - "url": "https://opencollective.com/postcss/" 3321 - }, 3322 - { 3323 - "type": "tidelift", 3324 - "url": "https://tidelift.com/funding/github/npm/postcss" 3325 - }, 3326 - { 3327 - "type": "github", 3328 - "url": "https://github.com/sponsors/ai" 3329 - } 3330 - ], 3331 - "license": "MIT", 3332 - "dependencies": { 3333 - "nanoid": "^3.3.8", 3334 - "picocolors": "^1.1.1", 3335 - "source-map-js": "^1.2.1" 3336 - }, 3337 - "engines": { 3338 - "node": "^10 || ^12 || >=14" 3339 - } 3340 - }, 3341 - "node_modules/prelude-ls": { 3342 - "version": "1.2.1", 3343 - "dev": true, 3344 - "license": "MIT", 3345 - "engines": { 3346 - "node": ">= 0.8.0" 3347 - } 3348 - }, 3349 - "node_modules/prop-types": { 3350 - "version": "15.8.1", 3351 - "license": "MIT", 3352 - "dependencies": { 3353 - "loose-envify": "^1.4.0", 3354 - "object-assign": "^4.1.1", 3355 - "react-is": "^16.13.1" 3356 - } 3357 - }, 3358 - "node_modules/prop-types/node_modules/react-is": { 3359 - "version": "16.13.1", 3360 - "license": "MIT" 3361 - }, 3362 - "node_modules/proxy-from-env": { 3363 - "version": "1.1.0", 3364 - "license": "MIT" 3365 - }, 3366 - "node_modules/punycode": { 3367 - "version": "2.3.1", 3368 - "dev": true, 3369 - "license": "MIT", 3370 - "engines": { 3371 - "node": ">=6" 3372 - } 3373 - }, 3374 - "node_modules/queue-microtask": { 3375 - "version": "1.2.3", 3376 - "dev": true, 3377 - "funding": [ 3378 - { 3379 - "type": "github", 3380 - "url": "https://github.com/sponsors/feross" 3381 - }, 3382 - { 3383 - "type": "patreon", 3384 - "url": "https://www.patreon.com/feross" 3385 - }, 3386 - { 3387 - "type": "consulting", 3388 - "url": "https://feross.org/support" 3389 - } 3390 - ], 3391 - "license": "MIT" 3392 - }, 3393 - "node_modules/react": { 3394 - "version": "18.3.1", 3395 - "license": "MIT", 3396 - "dependencies": { 3397 - "loose-envify": "^1.1.0" 3398 - }, 3399 - "engines": { 3400 - "node": ">=0.10.0" 3401 - } 3402 - }, 3403 - "node_modules/react-dom": { 3404 - "version": "18.3.1", 3405 - "license": "MIT", 3406 - "dependencies": { 3407 - "loose-envify": "^1.1.0", 3408 - "scheduler": "^0.23.2" 3409 - }, 3410 - "peerDependencies": { 3411 - "react": "^18.3.1" 3412 - } 3413 - }, 3414 - "node_modules/react-hook-form": { 3415 - "version": "7.54.2", 3416 - "license": "MIT", 3417 - "engines": { 3418 - "node": ">=18.0.0" 3419 - }, 3420 - "funding": { 3421 - "type": "opencollective", 3422 - "url": "https://opencollective.com/react-hook-form" 3423 - }, 3424 - "peerDependencies": { 3425 - "react": "^16.8.0 || ^17 || ^18 || ^19" 3426 - } 3427 - }, 3428 - "node_modules/react-is": { 3429 - "version": "18.3.1", 3430 - "license": "MIT" 3431 - }, 3432 - "node_modules/react-number-format": { 3433 - "version": "5.4.3", 3434 - "license": "MIT", 3435 - "peerDependencies": { 3436 - "react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", 3437 - "react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 3438 - } 3439 - }, 3440 - "node_modules/react-refresh": { 3441 - "version": "0.14.2", 3442 - "dev": true, 3443 - "license": "MIT", 3444 - "engines": { 3445 - "node": ">=0.10.0" 3446 - } 3447 - }, 3448 - "node_modules/react-remove-scroll": { 3449 - "version": "2.6.3", 3450 - "license": "MIT", 3451 - "dependencies": { 3452 - "react-remove-scroll-bar": "^2.3.7", 3453 - "react-style-singleton": "^2.2.3", 3454 - "tslib": "^2.1.0", 3455 - "use-callback-ref": "^1.3.3", 3456 - "use-sidecar": "^1.1.3" 3457 - }, 3458 - "engines": { 3459 - "node": ">=10" 3460 - }, 3461 - "peerDependencies": { 3462 - "@types/react": "*", 3463 - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" 3464 - }, 3465 - "peerDependenciesMeta": { 3466 - "@types/react": { 3467 - "optional": true 3468 - } 3469 - } 3470 - }, 3471 - "node_modules/react-remove-scroll-bar": { 3472 - "version": "2.3.8", 3473 - "license": "MIT", 3474 - "dependencies": { 3475 - "react-style-singleton": "^2.2.2", 3476 - "tslib": "^2.0.0" 3477 - }, 3478 - "engines": { 3479 - "node": ">=10" 3480 - }, 3481 - "peerDependencies": { 3482 - "@types/react": "*", 3483 - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 3484 - }, 3485 - "peerDependenciesMeta": { 3486 - "@types/react": { 3487 - "optional": true 3488 - } 3489 - } 3490 - }, 3491 - "node_modules/react-simple-icons": { 3492 - "version": "1.0.0-beta.5", 3493 - "license": "MIT", 3494 - "dependencies": { 3495 - "@jxnblk/simple-icons": "^1.0.0" 3496 - } 3497 - }, 3498 - "node_modules/react-smooth": { 3499 - "version": "4.0.4", 3500 - "license": "MIT", 3501 - "dependencies": { 3502 - "fast-equals": "^5.0.1", 3503 - "prop-types": "^15.8.1", 3504 - "react-transition-group": "^4.4.5" 3505 - }, 3506 - "peerDependencies": { 3507 - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", 3508 - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 3509 - } 3510 - }, 3511 - "node_modules/react-style-singleton": { 3512 - "version": "2.2.3", 3513 - "license": "MIT", 3514 - "dependencies": { 3515 - "get-nonce": "^1.0.0", 3516 - "tslib": "^2.0.0" 3517 - }, 3518 - "engines": { 3519 - "node": ">=10" 3520 - }, 3521 - "peerDependencies": { 3522 - "@types/react": "*", 3523 - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" 3524 - }, 3525 - "peerDependenciesMeta": { 3526 - "@types/react": { 3527 - "optional": true 3528 - } 3529 - } 3530 - }, 3531 - "node_modules/react-textarea-autosize": { 3532 - "version": "8.5.6", 3533 - "license": "MIT", 3534 - "dependencies": { 3535 - "@babel/runtime": "^7.20.13", 3536 - "use-composed-ref": "^1.3.0", 3537 - "use-latest": "^1.2.1" 3538 - }, 3539 - "engines": { 3540 - "node": ">=10" 3541 - }, 3542 - "peerDependencies": { 3543 - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 3544 - } 3545 - }, 3546 - "node_modules/react-transition-group": { 3547 - "version": "4.4.5", 3548 - "license": "BSD-3-Clause", 3549 - "dependencies": { 3550 - "@babel/runtime": "^7.5.5", 3551 - "dom-helpers": "^5.0.1", 3552 - "loose-envify": "^1.4.0", 3553 - "prop-types": "^15.6.2" 3554 - }, 3555 - "peerDependencies": { 3556 - "react": ">=16.6.0", 3557 - "react-dom": ">=16.6.0" 3558 - } 3559 - }, 3560 - "node_modules/recharts": { 3561 - "version": "2.15.0", 3562 - "license": "MIT", 3563 - "dependencies": { 3564 - "clsx": "^2.0.0", 3565 - "eventemitter3": "^4.0.1", 3566 - "lodash": "^4.17.21", 3567 - "react-is": "^18.3.1", 3568 - "react-smooth": "^4.0.0", 3569 - "recharts-scale": "^0.4.4", 3570 - "tiny-invariant": "^1.3.1", 3571 - "victory-vendor": "^36.6.8" 3572 - }, 3573 - "engines": { 3574 - "node": ">=14" 3575 - }, 3576 - "peerDependencies": { 3577 - "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", 3578 - "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 3579 - } 3580 - }, 3581 - "node_modules/recharts-scale": { 3582 - "version": "0.4.5", 3583 - "license": "MIT", 3584 - "dependencies": { 3585 - "decimal.js-light": "^2.4.1" 3586 - } 3587 - }, 3588 - "node_modules/regenerator-runtime": { 3589 - "version": "0.14.1", 3590 - "license": "MIT" 3591 - }, 3592 - "node_modules/resolve": { 3593 - "version": "1.22.10", 3594 - "license": "MIT", 3595 - "dependencies": { 3596 - "is-core-module": "^2.16.0", 3597 - "path-parse": "^1.0.7", 3598 - "supports-preserve-symlinks-flag": "^1.0.0" 3599 - }, 3600 - "bin": { 3601 - "resolve": "bin/resolve" 3602 - }, 3603 - "engines": { 3604 - "node": ">= 0.4" 3605 - }, 3606 - "funding": { 3607 - "url": "https://github.com/sponsors/ljharb" 3608 - } 3609 - }, 3610 - "node_modules/resolve-from": { 3611 - "version": "4.0.0", 3612 - "license": "MIT", 3613 - "engines": { 3614 - "node": ">=4" 3615 - } 3616 - }, 3617 - "node_modules/reusify": { 3618 - "version": "1.0.4", 3619 - "dev": true, 3620 - "license": "MIT", 3621 - "engines": { 3622 - "iojs": ">=1.0.0", 3623 - "node": ">=0.10.0" 3624 - } 3625 - }, 3626 - "node_modules/rollup": { 3627 - "version": "4.32.0", 3628 - "license": "MIT", 3629 - "dependencies": { 3630 - "@types/estree": "1.0.6" 3631 - }, 3632 - "bin": { 3633 - "rollup": "dist/bin/rollup" 3634 - }, 3635 - "engines": { 3636 - "node": ">=18.0.0", 3637 - "npm": ">=8.0.0" 3638 - }, 3639 - "optionalDependencies": { 3640 - "@rollup/rollup-android-arm-eabi": "4.32.0", 3641 - "@rollup/rollup-android-arm64": "4.32.0", 3642 - "@rollup/rollup-darwin-arm64": "4.32.0", 3643 - "@rollup/rollup-darwin-x64": "4.32.0", 3644 - "@rollup/rollup-freebsd-arm64": "4.32.0", 3645 - "@rollup/rollup-freebsd-x64": "4.32.0", 3646 - "@rollup/rollup-linux-arm-gnueabihf": "4.32.0", 3647 - "@rollup/rollup-linux-arm-musleabihf": "4.32.0", 3648 - "@rollup/rollup-linux-arm64-gnu": "4.32.0", 3649 - "@rollup/rollup-linux-arm64-musl": "4.32.0", 3650 - "@rollup/rollup-linux-loongarch64-gnu": "4.32.0", 3651 - "@rollup/rollup-linux-powerpc64le-gnu": "4.32.0", 3652 - "@rollup/rollup-linux-riscv64-gnu": "4.32.0", 3653 - "@rollup/rollup-linux-s390x-gnu": "4.32.0", 3654 - "@rollup/rollup-linux-x64-gnu": "4.32.0", 3655 - "@rollup/rollup-linux-x64-musl": "4.32.0", 3656 - "@rollup/rollup-win32-arm64-msvc": "4.32.0", 3657 - "@rollup/rollup-win32-ia32-msvc": "4.32.0", 3658 - "@rollup/rollup-win32-x64-msvc": "4.32.0", 3659 - "fsevents": "~2.3.2" 3660 - } 3661 - }, 3662 - "node_modules/run-parallel": { 3663 - "version": "1.2.0", 3664 - "dev": true, 3665 - "funding": [ 3666 - { 3667 - "type": "github", 3668 - "url": "https://github.com/sponsors/feross" 3669 - }, 3670 - { 3671 - "type": "patreon", 3672 - "url": "https://www.patreon.com/feross" 3673 - }, 3674 - { 3675 - "type": "consulting", 3676 - "url": "https://feross.org/support" 3677 - } 3678 - ], 3679 - "license": "MIT", 3680 - "dependencies": { 3681 - "queue-microtask": "^1.2.2" 3682 - } 3683 - }, 3684 - "node_modules/scheduler": { 3685 - "version": "0.23.2", 3686 - "license": "MIT", 3687 - "dependencies": { 3688 - "loose-envify": "^1.1.0" 3689 - } 3690 - }, 3691 - "node_modules/semver": { 3692 - "version": "6.3.1", 3693 - "dev": true, 3694 - "license": "ISC", 3695 - "bin": { 3696 - "semver": "bin/semver.js" 3697 - } 3698 - }, 3699 - "node_modules/shebang-command": { 3700 - "version": "2.0.0", 3701 - "dev": true, 3702 - "license": "MIT", 3703 - "dependencies": { 3704 - "shebang-regex": "^3.0.0" 3705 - }, 3706 - "engines": { 3707 - "node": ">=8" 3708 - } 3709 - }, 3710 - "node_modules/shebang-regex": { 3711 - "version": "3.0.0", 3712 - "dev": true, 3713 - "license": "MIT", 3714 - "engines": { 3715 - "node": ">=8" 3716 - } 3717 - }, 3718 - "node_modules/simple-icons": { 3719 - "version": "14.4.0", 3720 - "license": "CC0-1.0", 3721 - "engines": { 3722 - "node": ">=0.12.18" 3723 - }, 3724 - "funding": { 3725 - "type": "opencollective", 3726 - "url": "https://opencollective.com/simple-icons" 3727 - } 3728 - }, 3729 - "node_modules/source-map": { 3730 - "version": "0.5.7", 3731 - "license": "BSD-3-Clause", 3732 - "engines": { 3733 - "node": ">=0.10.0" 3734 - } 3735 - }, 3736 - "node_modules/source-map-js": { 3737 - "version": "1.2.1", 3738 - "license": "BSD-3-Clause", 3739 - "engines": { 3740 - "node": ">=0.10.0" 3741 - } 3742 - }, 3743 - "node_modules/strip-json-comments": { 3744 - "version": "3.1.1", 3745 - "dev": true, 3746 - "license": "MIT", 3747 - "engines": { 3748 - "node": ">=8" 3749 - }, 3750 - "funding": { 3751 - "url": "https://github.com/sponsors/sindresorhus" 3752 - } 3753 - }, 3754 - "node_modules/stylis": { 3755 - "version": "4.2.0", 3756 - "license": "MIT" 3757 - }, 3758 - "node_modules/supports-color": { 3759 - "version": "7.2.0", 3760 - "dev": true, 3761 - "license": "MIT", 3762 - "dependencies": { 3763 - "has-flag": "^4.0.0" 3764 - }, 3765 - "engines": { 3766 - "node": ">=8" 3767 - } 3768 - }, 3769 - "node_modules/supports-preserve-symlinks-flag": { 3770 - "version": "1.0.0", 3771 - "license": "MIT", 3772 - "engines": { 3773 - "node": ">= 0.4" 3774 - }, 3775 - "funding": { 3776 - "url": "https://github.com/sponsors/ljharb" 3777 - } 3778 - }, 3779 - "node_modules/tabbable": { 3780 - "version": "6.2.0", 3781 - "license": "MIT" 3782 - }, 3783 - "node_modules/tailwind-merge": { 3784 - "version": "2.6.0", 3785 - "license": "MIT", 3786 - "funding": { 3787 - "type": "github", 3788 - "url": "https://github.com/sponsors/dcastil" 3789 - } 3790 - }, 3791 - "node_modules/tailwindcss": { 3792 - "version": "4.0.0", 3793 - "license": "MIT" 3794 - }, 3795 - "node_modules/tailwindcss-animate": { 3796 - "version": "1.0.7", 3797 - "license": "MIT", 3798 - "peerDependencies": { 3799 - "tailwindcss": ">=3.0.0 || insiders" 3800 - } 3801 - }, 3802 - "node_modules/tapable": { 3803 - "version": "2.2.1", 3804 - "license": "MIT", 3805 - "engines": { 3806 - "node": ">=6" 3807 - } 3808 - }, 3809 - "node_modules/tiny-invariant": { 3810 - "version": "1.3.3", 3811 - "license": "MIT" 3812 - }, 3813 - "node_modules/to-regex-range": { 3814 - "version": "5.0.1", 3815 - "dev": true, 3816 - "license": "MIT", 3817 - "dependencies": { 3818 - "is-number": "^7.0.0" 3819 - }, 3820 - "engines": { 3821 - "node": ">=8.0" 3822 - } 3823 - }, 3824 - "node_modules/ts-api-utils": { 3825 - "version": "2.0.0", 3826 - "dev": true, 3827 - "license": "MIT", 3828 - "engines": { 3829 - "node": ">=18.12" 3830 - }, 3831 - "peerDependencies": { 3832 - "typescript": ">=4.8.4" 3833 - } 3834 - }, 3835 - "node_modules/tslib": { 3836 - "version": "2.8.1", 3837 - "license": "0BSD" 3838 - }, 3839 - "node_modules/type-check": { 3840 - "version": "0.4.0", 3841 - "dev": true, 3842 - "license": "MIT", 3843 - "dependencies": { 3844 - "prelude-ls": "^1.2.1" 3845 - }, 3846 - "engines": { 3847 - "node": ">= 0.8.0" 3848 - } 3849 - }, 3850 - "node_modules/type-fest": { 3851 - "version": "4.33.0", 3852 - "license": "(MIT OR CC0-1.0)", 3853 - "engines": { 3854 - "node": ">=16" 3855 - }, 3856 - "funding": { 3857 - "url": "https://github.com/sponsors/sindresorhus" 3858 - } 3859 - }, 3860 - "node_modules/typescript": { 3861 - "version": "5.6.3", 3862 - "dev": true, 3863 - "license": "Apache-2.0", 3864 - "bin": { 3865 - "tsc": "bin/tsc", 3866 - "tsserver": "bin/tsserver" 3867 - }, 3868 - "engines": { 3869 - "node": ">=14.17" 3870 - } 3871 - }, 3872 - "node_modules/typescript-eslint": { 3873 - "version": "8.21.0", 3874 - "dev": true, 3875 - "license": "MIT", 3876 - "dependencies": { 3877 - "@typescript-eslint/eslint-plugin": "8.21.0", 3878 - "@typescript-eslint/parser": "8.21.0", 3879 - "@typescript-eslint/utils": "8.21.0" 3880 - }, 3881 - "engines": { 3882 - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 3883 - }, 3884 - "funding": { 3885 - "type": "opencollective", 3886 - "url": "https://opencollective.com/typescript-eslint" 3887 - }, 3888 - "peerDependencies": { 3889 - "eslint": "^8.57.0 || ^9.0.0", 3890 - "typescript": ">=4.8.4 <5.8.0" 3891 - } 3892 - }, 3893 - "node_modules/undici-types": { 3894 - "version": "6.20.0", 3895 - "devOptional": true, 3896 - "license": "MIT" 3897 - }, 3898 - "node_modules/update-browserslist-db": { 3899 - "version": "1.1.2", 3900 - "dev": true, 3901 - "funding": [ 3902 - { 3903 - "type": "opencollective", 3904 - "url": "https://opencollective.com/browserslist" 3905 - }, 3906 - { 3907 - "type": "tidelift", 3908 - "url": "https://tidelift.com/funding/github/npm/browserslist" 3909 - }, 3910 - { 3911 - "type": "github", 3912 - "url": "https://github.com/sponsors/ai" 3913 - } 3914 - ], 3915 - "license": "MIT", 3916 - "dependencies": { 3917 - "escalade": "^3.2.0", 3918 - "picocolors": "^1.1.1" 3919 - }, 3920 - "bin": { 3921 - "update-browserslist-db": "cli.js" 3922 - }, 3923 - "peerDependencies": { 3924 - "browserslist": ">= 4.21.0" 3925 - } 3926 - }, 3927 - "node_modules/uri-js": { 3928 - "version": "4.4.1", 3929 - "dev": true, 3930 - "license": "BSD-2-Clause", 3931 - "dependencies": { 3932 - "punycode": "^2.1.0" 3933 - } 3934 - }, 3935 - "node_modules/use-callback-ref": { 3936 - "version": "1.3.3", 3937 - "license": "MIT", 3938 - "dependencies": { 3939 - "tslib": "^2.0.0" 3940 - }, 3941 - "engines": { 3942 - "node": ">=10" 3943 - }, 3944 - "peerDependencies": { 3945 - "@types/react": "*", 3946 - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" 3947 - }, 3948 - "peerDependenciesMeta": { 3949 - "@types/react": { 3950 - "optional": true 3951 - } 3952 - } 3953 - }, 3954 - "node_modules/use-composed-ref": { 3955 - "version": "1.4.0", 3956 - "license": "MIT", 3957 - "peerDependencies": { 3958 - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 3959 - }, 3960 - "peerDependenciesMeta": { 3961 - "@types/react": { 3962 - "optional": true 3963 - } 3964 - } 3965 - }, 3966 - "node_modules/use-isomorphic-layout-effect": { 3967 - "version": "1.2.0", 3968 - "license": "MIT", 3969 - "peerDependencies": { 3970 - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 3971 - }, 3972 - "peerDependenciesMeta": { 3973 - "@types/react": { 3974 - "optional": true 3975 - } 3976 - } 3977 - }, 3978 - "node_modules/use-latest": { 3979 - "version": "1.3.0", 3980 - "license": "MIT", 3981 - "dependencies": { 3982 - "use-isomorphic-layout-effect": "^1.1.1" 3983 - }, 3984 - "peerDependencies": { 3985 - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 3986 - }, 3987 - "peerDependenciesMeta": { 3988 - "@types/react": { 3989 - "optional": true 3990 - } 3991 - } 3992 - }, 3993 - "node_modules/use-sidecar": { 3994 - "version": "1.1.3", 3995 - "license": "MIT", 3996 - "dependencies": { 3997 - "detect-node-es": "^1.1.0", 3998 - "tslib": "^2.0.0" 3999 - }, 4000 - "engines": { 4001 - "node": ">=10" 4002 - }, 4003 - "peerDependencies": { 4004 - "@types/react": "*", 4005 - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" 4006 - }, 4007 - "peerDependenciesMeta": { 4008 - "@types/react": { 4009 - "optional": true 4010 - } 4011 - } 4012 - }, 4013 - "node_modules/victory-vendor": { 4014 - "version": "36.9.2", 4015 - "license": "MIT AND ISC", 4016 - "dependencies": { 4017 - "@types/d3-array": "^3.0.3", 4018 - "@types/d3-ease": "^3.0.0", 4019 - "@types/d3-interpolate": "^3.0.1", 4020 - "@types/d3-scale": "^4.0.2", 4021 - "@types/d3-shape": "^3.1.0", 4022 - "@types/d3-time": "^3.0.0", 4023 - "@types/d3-timer": "^3.0.0", 4024 - "d3-array": "^3.1.6", 4025 - "d3-ease": "^3.0.1", 4026 - "d3-interpolate": "^3.0.1", 4027 - "d3-scale": "^4.0.2", 4028 - "d3-shape": "^3.1.0", 4029 - "d3-time": "^3.0.0", 4030 - "d3-timer": "^3.0.1" 4031 - } 4032 - }, 4033 - "node_modules/vite": { 4034 - "version": "6.0.11", 4035 - "license": "MIT", 4036 - "dependencies": { 4037 - "esbuild": "^0.24.2", 4038 - "postcss": "^8.4.49", 4039 - "rollup": "^4.23.0" 4040 - }, 4041 - "bin": { 4042 - "vite": "bin/vite.js" 4043 - }, 4044 - "engines": { 4045 - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 4046 - }, 4047 - "funding": { 4048 - "url": "https://github.com/vitejs/vite?sponsor=1" 4049 - }, 4050 - "optionalDependencies": { 4051 - "fsevents": "~2.3.3" 4052 - }, 4053 - "peerDependencies": { 4054 - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", 4055 - "jiti": ">=1.21.0", 4056 - "less": "*", 4057 - "lightningcss": "^1.21.0", 4058 - "sass": "*", 4059 - "sass-embedded": "*", 4060 - "stylus": "*", 4061 - "sugarss": "*", 4062 - "terser": "^5.16.0", 4063 - "tsx": "^4.8.1", 4064 - "yaml": "^2.4.2" 4065 - }, 4066 - "peerDependenciesMeta": { 4067 - "@types/node": { 4068 - "optional": true 4069 - }, 4070 - "jiti": { 4071 - "optional": true 4072 - }, 4073 - "less": { 4074 - "optional": true 4075 - }, 4076 - "lightningcss": { 4077 - "optional": true 4078 - }, 4079 - "sass": { 4080 - "optional": true 4081 - }, 4082 - "sass-embedded": { 4083 - "optional": true 4084 - }, 4085 - "stylus": { 4086 - "optional": true 4087 - }, 4088 - "sugarss": { 4089 - "optional": true 4090 - }, 4091 - "terser": { 4092 - "optional": true 4093 - }, 4094 - "tsx": { 4095 - "optional": true 4096 - }, 4097 - "yaml": { 4098 - "optional": true 4099 - } 4100 - } 4101 - }, 4102 - "node_modules/which": { 4103 - "version": "2.0.2", 4104 - "dev": true, 4105 - "license": "ISC", 4106 - "dependencies": { 4107 - "isexe": "^2.0.0" 4108 - }, 4109 - "bin": { 4110 - "node-which": "bin/node-which" 4111 - }, 4112 - "engines": { 4113 - "node": ">= 8" 4114 - } 4115 - }, 4116 - "node_modules/word-wrap": { 4117 - "version": "1.2.5", 4118 - "dev": true, 4119 - "license": "MIT", 4120 - "engines": { 4121 - "node": ">=0.10.0" 4122 - } 4123 - }, 4124 - "node_modules/yallist": { 4125 - "version": "3.1.1", 4126 - "dev": true, 4127 - "license": "ISC" 4128 - }, 4129 - "node_modules/yaml": { 4130 - "version": "2.7.0", 4131 - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", 4132 - "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", 4133 - "license": "ISC", 4134 - "optional": true, 4135 - "peer": true, 4136 - "bin": { 4137 - "yaml": "bin.mjs" 4138 - }, 4139 - "engines": { 4140 - "node": ">= 14" 4141 - } 4142 - }, 4143 - "node_modules/yocto-queue": { 4144 - "version": "0.1.0", 4145 - "dev": true, 4146 - "license": "MIT", 4147 - "engines": { 4148 - "node": ">=10" 4149 - }, 4150 - "funding": { 4151 - "url": "https://github.com/sponsors/sindresorhus" 4152 - } 4153 - }, 4154 - "node_modules/zod": { 4155 - "version": "3.24.1", 4156 - "license": "MIT", 4157 - "funding": { 4158 - "url": "https://github.com/sponsors/colinhacks" 4159 - } 4160 - } 4161 - } 4162 - }
+40 -4
frontend/src/api/client.ts
··· 15 15 return config; 16 16 }); 17 17 18 + api.interceptors.response.use( 19 + (response) => response, 20 + (error) => { 21 + if (error.response?.status === 401) { 22 + localStorage.removeItem('token'); 23 + localStorage.removeItem('user'); 24 + 25 + window.dispatchEvent(new Event('unauthorized')); 26 + } 27 + return Promise.reject(error); 28 + } 29 + ); 30 + 31 + 18 32 // Auth endpoints 19 33 export const login = async (email: string, password: string) => { 20 34 const response = await api.post<AuthResponse>('/auth/login', { ··· 44 58 return response.data; 45 59 }; 46 60 61 + export const editLink = async (id: number, data: Partial<CreateLinkRequest>) => { 62 + const response = await api.patch<Link>(`/links/${id}`, data); 63 + return response.data; 64 + }; 65 + 66 + 47 67 export const deleteLink = async (id: number) => { 48 68 await api.delete(`/links/${id}`); 49 69 }; 50 70 51 71 export const getLinkClickStats = async (id: number) => { 52 - const response = await api.get<ClickStats[]>(`/links/${id}/clicks`); 53 - return response.data; 72 + try { 73 + const response = await api.get<ClickStats[]>(`/links/${id}/clicks`); 74 + return response.data; 75 + } catch (error) { 76 + console.error('Error fetching click stats:', error); 77 + throw error; 78 + } 54 79 }; 55 80 56 81 export const getLinkSourceStats = async (id: number) => { 57 - const response = await api.get<SourceStats[]>(`/links/${id}/sources`); 58 - return response.data; 82 + try { 83 + const response = await api.get<SourceStats[]>(`/links/${id}/sources`); 84 + return response.data; 85 + } catch (error) { 86 + console.error('Error fetching source stats:', error); 87 + throw error; 88 + } 89 + }; 90 + 91 + 92 + export const checkFirstUser = async () => { 93 + const response = await api.get<{ isFirstUser: boolean }>('/auth/check-first-user'); 94 + return response.data.isFirstUser; 59 95 }; 60 96 61 97 export { api };
+82 -62
frontend/src/components/AuthForms.tsx
··· 1 - import { useState } from 'react' 1 + import { useState, useEffect } from 'react' 2 2 import { useForm } from 'react-hook-form' 3 3 import { z } from 'zod' 4 4 import { zodResolver } from '@hookform/resolvers/zod' ··· 6 6 import { Button } from '@/components/ui/button' 7 7 import { Input } from '@/components/ui/input' 8 8 import { Card } from '@/components/ui/card' 9 - import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' 10 9 import { 11 10 Form, 12 11 FormControl, ··· 16 15 FormMessage, 17 16 } from '@/components/ui/form' 18 17 import { useToast } from '@/hooks/use-toast' 18 + import { checkFirstUser } from '../api/client' 19 19 20 20 const formSchema = z.object({ 21 21 email: z.string().email('Invalid email address'), 22 22 password: z.string().min(6, 'Password must be at least 6 characters long'), 23 - adminToken: z.string(), 23 + adminToken: z.string().optional(), 24 24 }) 25 25 26 26 type FormValues = z.infer<typeof formSchema> 27 27 28 28 export function AuthForms() { 29 - const [activeTab, setActiveTab] = useState<'login' | 'register'>('login') 29 + const [isFirstUser, setIsFirstUser] = useState<boolean | null>(null) 30 30 const { login, register } = useAuth() 31 31 const { toast } = useToast() 32 32 ··· 39 39 }, 40 40 }) 41 41 42 + useEffect(() => { 43 + const init = async () => { 44 + try { 45 + const isFirst = await checkFirstUser() 46 + setIsFirstUser(isFirst) 47 + } catch (err) { 48 + console.error('Error checking first user:', err) 49 + setIsFirstUser(false) 50 + } 51 + } 52 + 53 + init() 54 + }, []) 55 + 42 56 const onSubmit = async (values: FormValues) => { 43 57 try { 44 - if (activeTab === 'login') { 45 - await login(values.email, values.password) 58 + if (isFirstUser) { 59 + await register(values.email, values.password, values.adminToken || '') 46 60 } else { 47 - await register(values.email, values.password, values.adminToken) 61 + await login(values.email, values.password) 48 62 } 49 63 form.reset() 50 64 } catch (err: any) { ··· 56 70 } 57 71 } 58 72 73 + if (isFirstUser === null) { 74 + return <div>Loading...</div> 75 + } 76 + 59 77 return ( 60 78 <Card className="w-full max-w-md mx-auto p-6"> 61 - <Tabs value={activeTab} onValueChange={(value: string) => setActiveTab(value as 'login' | 'register')}> 62 - <TabsList className="grid w-full grid-cols-2"> 63 - <TabsTrigger value="login">Login</TabsTrigger> 64 - <TabsTrigger value="register">Register</TabsTrigger> 65 - </TabsList> 79 + <div className="mb-6 text-center"> 80 + <h2 className="text-2xl font-bold"> 81 + {isFirstUser ? 'Create Admin Account' : 'Login'} 82 + </h2> 83 + <p className="text-sm text-muted-foreground mt-1"> 84 + {isFirstUser 85 + ? 'Set up your admin account to get started' 86 + : 'Welcome back! Please login to your account'} 87 + </p> 88 + </div> 66 89 67 - <TabsContent value={activeTab}> 68 - <Form {...form}> 69 - <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4"> 70 - <FormField 71 - control={form.control} 72 - name="email" 73 - render={({ field }) => ( 74 - <FormItem> 75 - <FormLabel>Email</FormLabel> 76 - <FormControl> 77 - <Input type="email" {...field} /> 78 - </FormControl> 79 - <FormMessage /> 80 - </FormItem> 81 - )} 82 - /> 90 + <Form {...form}> 91 + <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4"> 92 + <FormField 93 + control={form.control} 94 + name="email" 95 + render={({ field }) => ( 96 + <FormItem> 97 + <FormLabel>Email</FormLabel> 98 + <FormControl> 99 + <Input type="email" {...field} /> 100 + </FormControl> 101 + <FormMessage /> 102 + </FormItem> 103 + )} 104 + /> 83 105 84 - <FormField 85 - control={form.control} 86 - name="password" 87 - render={({ field }) => ( 88 - <FormItem> 89 - <FormLabel>Password</FormLabel> 90 - <FormControl> 91 - <Input type="password" {...field} /> 92 - </FormControl> 93 - <FormMessage /> 94 - </FormItem> 95 - )} 96 - /> 106 + <FormField 107 + control={form.control} 108 + name="password" 109 + render={({ field }) => ( 110 + <FormItem> 111 + <FormLabel>Password</FormLabel> 112 + <FormControl> 113 + <Input type="password" {...field} /> 114 + </FormControl> 115 + <FormMessage /> 116 + </FormItem> 117 + )} 118 + /> 97 119 98 - {activeTab === 'register' && ( 99 - <FormField 100 - control={form.control} 101 - name="adminToken" 102 - render={({ field }) => ( 103 - <FormItem> 104 - <FormLabel>Admin Setup Token</FormLabel> 105 - <FormControl> 106 - <Input type="text" {...field} /> 107 - </FormControl> 108 - <FormMessage /> 109 - </FormItem> 110 - )} 111 - /> 120 + {isFirstUser && ( 121 + <FormField 122 + control={form.control} 123 + name="adminToken" 124 + render={({ field }) => ( 125 + <FormItem> 126 + <FormLabel>Admin Setup Token</FormLabel> 127 + <FormControl> 128 + <Input type="text" {...field} /> 129 + </FormControl> 130 + <FormMessage /> 131 + </FormItem> 112 132 )} 133 + /> 134 + )} 113 135 114 - <Button type="submit" className="w-full"> 115 - {activeTab === 'login' ? 'Sign in' : 'Create account'} 116 - </Button> 117 - </form> 118 - </Form> 119 - </TabsContent> 120 - </Tabs> 136 + <Button type="submit" className="w-full"> 137 + {isFirstUser ? 'Create Account' : 'Sign in'} 138 + </Button> 139 + </form> 140 + </Form> 121 141 </Card> 122 142 ) 123 143 }
+139
frontend/src/components/EditModal.tsx
··· 1 + // src/components/EditModal.tsx 2 + import { useState } from 'react'; 3 + import { useForm } from 'react-hook-form'; 4 + import { zodResolver } from '@hookform/resolvers/zod'; 5 + import * as z from 'zod'; 6 + import { Link } from '../types/api'; 7 + import { editLink } from '../api/client'; 8 + import { useToast } from '@/hooks/use-toast'; 9 + import { 10 + Dialog, 11 + DialogContent, 12 + DialogHeader, 13 + DialogTitle, 14 + DialogFooter, 15 + } from '@/components/ui/dialog'; 16 + import { Button } from '@/components/ui/button'; 17 + import { Input } from '@/components/ui/input'; 18 + import { 19 + Form, 20 + FormControl, 21 + FormField, 22 + FormItem, 23 + FormLabel, 24 + FormMessage, 25 + } from '@/components/ui/form'; 26 + 27 + const formSchema = z.object({ 28 + url: z 29 + .string() 30 + .min(1, 'URL is required') 31 + .url('Must be a valid URL') 32 + .refine((val) => val.startsWith('http://') || val.startsWith('https://'), { 33 + message: 'URL must start with http:// or https://', 34 + }), 35 + custom_code: z 36 + .string() 37 + .regex(/^[a-zA-Z0-9_-]{1,32}$/, { 38 + message: 39 + 'Custom code must be 1-32 characters and contain only letters, numbers, underscores, and hyphens', 40 + }) 41 + .optional(), 42 + }); 43 + 44 + interface EditModalProps { 45 + isOpen: boolean; 46 + onClose: () => void; 47 + link: Link; 48 + onSuccess: () => void; 49 + } 50 + 51 + export function EditModal({ isOpen, onClose, link, onSuccess }: EditModalProps) { 52 + const [loading, setLoading] = useState(false); 53 + const { toast } = useToast(); 54 + 55 + const form = useForm<z.infer<typeof formSchema>>({ 56 + resolver: zodResolver(formSchema), 57 + defaultValues: { 58 + url: link.original_url, 59 + custom_code: link.short_code, 60 + }, 61 + }); 62 + 63 + const onSubmit = async (values: z.infer<typeof formSchema>) => { 64 + try { 65 + setLoading(true); 66 + await editLink(link.id, values); 67 + toast({ 68 + description: 'Link updated successfully', 69 + }); 70 + onSuccess(); 71 + onClose(); 72 + } catch (err: unknown) { 73 + const error = err as { response?: { data?: { error?: string } } }; 74 + toast({ 75 + variant: 'destructive', 76 + title: 'Error', 77 + description: error.response?.data?.error || 'Failed to update link', 78 + }); 79 + } finally { 80 + setLoading(false); 81 + } 82 + }; 83 + 84 + return ( 85 + <Dialog open={isOpen} onOpenChange={onClose}> 86 + <DialogContent> 87 + <DialogHeader> 88 + <DialogTitle>Edit Link</DialogTitle> 89 + </DialogHeader> 90 + 91 + <Form {...form}> 92 + <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4"> 93 + <FormField 94 + control={form.control} 95 + name="url" 96 + render={({ field }) => ( 97 + <FormItem> 98 + <FormLabel>Destination URL</FormLabel> 99 + <FormControl> 100 + <Input placeholder="https://example.com" {...field} /> 101 + </FormControl> 102 + <FormMessage /> 103 + </FormItem> 104 + )} 105 + /> 106 + 107 + <FormField 108 + control={form.control} 109 + name="custom_code" 110 + render={({ field }) => ( 111 + <FormItem> 112 + <FormLabel>Short Code</FormLabel> 113 + <FormControl> 114 + <Input placeholder="custom-code" {...field} /> 115 + </FormControl> 116 + <FormMessage /> 117 + </FormItem> 118 + )} 119 + /> 120 + 121 + <DialogFooter> 122 + <Button 123 + type="button" 124 + variant="outline" 125 + onClick={onClose} 126 + disabled={loading} 127 + > 128 + Cancel 129 + </Button> 130 + <Button type="submit" disabled={loading}> 131 + {loading ? 'Saving...' : 'Save Changes'} 132 + </Button> 133 + </DialogFooter> 134 + </form> 135 + </Form> 136 + </DialogContent> 137 + </Dialog> 138 + ); 139 + }
+45 -14
frontend/src/components/LinkList.tsx
··· 1 - import { useEffect, useState } from 'react' 1 + import { useCallback, useEffect, useState } from 'react' 2 2 import { Link } from '../types/api' 3 3 import { getAllLinks, deleteLink } from '../api/client' 4 4 import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" ··· 12 12 } from "@/components/ui/table" 13 13 import { Button } from "@/components/ui/button" 14 14 import { useToast } from "@/hooks/use-toast" 15 - import { Copy, Trash2, BarChart2 } from "lucide-react" 15 + import { Copy, Trash2, BarChart2, Pencil } from "lucide-react" 16 16 import { 17 17 Dialog, 18 18 DialogContent, ··· 23 23 } from "@/components/ui/dialog" 24 24 25 25 import { StatisticsModal } from "./StatisticsModal" 26 + import { EditModal } from './EditModal' 26 27 27 28 interface LinkListProps { 28 29 refresh?: number; ··· 39 40 isOpen: false, 40 41 linkId: null, 41 42 }); 43 + const [editModal, setEditModal] = useState<{ isOpen: boolean; link: Link | null }>({ 44 + isOpen: false, 45 + link: null, 46 + }); 42 47 const { toast } = useToast() 43 48 44 - const fetchLinks = async () => { 49 + const fetchLinks = useCallback(async () => { 45 50 try { 46 51 setLoading(true) 47 52 const data = await getAllLinks() 48 53 setLinks(data) 49 - } catch (err) { 54 + } catch (err: unknown) { 55 + const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred'; 50 56 toast({ 51 57 title: "Error", 52 - description: "Failed to load links", 58 + description: `Failed to load links: ${errorMessage}`, 53 59 variant: "destructive", 54 60 }) 55 61 } finally { 56 62 setLoading(false) 57 63 } 58 - } 64 + }, [toast, setLinks, setLoading]) 59 65 60 66 useEffect(() => { 61 67 fetchLinks() 62 - }, [refresh]) // Re-fetch when refresh counter changes 68 + }, [fetchLinks, refresh]) // Re-fetch when refresh counter changes 63 69 64 70 const handleDelete = async () => { 65 71 if (!deleteModal.linkId) return ··· 71 77 toast({ 72 78 description: "Link deleted successfully", 73 79 }) 74 - } catch (err) { 80 + } catch (err: unknown) { 81 + const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred'; 75 82 toast({ 76 83 title: "Error", 77 - description: "Failed to delete link", 84 + description: `Failed to delete link: ${errorMessage}`, 78 85 variant: "destructive", 79 86 }) 80 87 } ··· 82 89 83 90 const handleCopy = (shortCode: string) => { 84 91 // Use import.meta.env.VITE_BASE_URL or fall back to window.location.origin 85 - const baseUrl = import.meta.env.VITE_API_URL || window.location.origin 92 + const baseUrl = window.location.origin 86 93 navigator.clipboard.writeText(`${baseUrl}/${shortCode}`) 87 94 toast({ 88 - description: "Link copied to clipboard", 95 + description: ( 96 + <> 97 + Link copied to clipboard 98 + <br /> 99 + You can add ?source=TextHere to the end of the link to track the source of clicks 100 + </> 101 + ), 89 102 }) 90 103 } 91 104 ··· 121 134 </CardHeader> 122 135 <CardContent> 123 136 <div className="rounded-md border"> 137 + 124 138 <Table> 125 139 <TableHeader> 126 140 <TableRow> ··· 128 142 <TableHead className="hidden md:table-cell">Original URL</TableHead> 129 143 <TableHead>Clicks</TableHead> 130 144 <TableHead className="hidden md:table-cell">Created</TableHead> 131 - <TableHead>Actions</TableHead> 145 + <TableHead className="w-[1%] whitespace-nowrap pr-4">Actions</TableHead> 132 146 </TableRow> 133 147 </TableHeader> 134 148 <TableBody> ··· 142 156 <TableCell className="hidden md:table-cell"> 143 157 {new Date(link.created_at).toLocaleDateString()} 144 158 </TableCell> 145 - <TableCell> 146 - <div className="flex gap-2"> 159 + <TableCell className="p-2 pr-4"> 160 + <div className="flex items-center gap-1"> 147 161 <Button 148 162 variant="ghost" 149 163 size="icon" ··· 165 179 <Button 166 180 variant="ghost" 167 181 size="icon" 182 + className="h-8 w-8" 183 + onClick={() => setEditModal({ isOpen: true, link })} 184 + > 185 + <Pencil className="h-4 w-4" /> 186 + <span className="sr-only">Edit Link</span> 187 + </Button> 188 + <Button 189 + variant="ghost" 190 + size="icon" 168 191 className="h-8 w-8 text-destructive" 169 192 onClick={() => setDeleteModal({ isOpen: true, linkId: link.id })} 170 193 > ··· 185 208 onClose={() => setStatsModal({ isOpen: false, linkId: null })} 186 209 linkId={statsModal.linkId!} 187 210 /> 211 + {editModal.link && ( 212 + <EditModal 213 + isOpen={editModal.isOpen} 214 + onClose={() => setEditModal({ isOpen: false, link: null })} 215 + link={editModal.link} 216 + onSuccess={fetchLinks} 217 + /> 218 + )} 188 219 </> 189 220 ) 190 221 }
+160 -98
frontend/src/components/StatisticsModal.tsx
··· 1 1 import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"; 2 2 import { 3 - LineChart, 4 - Line, 5 - XAxis, 6 - YAxis, 7 - CartesianGrid, 8 - Tooltip, 9 - ResponsiveContainer, 3 + LineChart, 4 + Line, 5 + XAxis, 6 + YAxis, 7 + CartesianGrid, 8 + Tooltip, 9 + ResponsiveContainer, 10 10 } from "recharts"; 11 11 import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; 12 - import { useState, useEffect } from "react"; 12 + import { toast } from "@/hooks/use-toast"; 13 + import { useState, useEffect, useMemo } from "react"; 13 14 14 - import { getLinkClickStats, getLinkSourceStats } from '../api/client'; 15 - import { ClickStats, SourceStats } from '../types/api'; 15 + import { getLinkClickStats, getLinkSourceStats } from "../api/client"; 16 + import { ClickStats, SourceStats } from "../types/api"; 16 17 17 18 interface StatisticsModalProps { 18 - isOpen: boolean; 19 - onClose: () => void; 20 - linkId: number; 19 + isOpen: boolean; 20 + onClose: () => void; 21 + linkId: number; 21 22 } 22 23 24 + interface EnhancedClickStats extends ClickStats { 25 + sources?: { source: string; count: number }[]; 26 + } 27 + 28 + const CustomTooltip = ({ 29 + active, 30 + payload, 31 + label, 32 + }: { 33 + active?: boolean; 34 + payload?: { value: number; payload: EnhancedClickStats }[]; 35 + label?: string; 36 + }) => { 37 + if (active && payload && payload.length > 0) { 38 + const data = payload[0].payload; 39 + return ( 40 + <div className="bg-background text-foreground p-4 rounded-lg shadow-lg border"> 41 + <p className="font-medium">{label}</p> 42 + <p className="text-sm">Clicks: {data.clicks}</p> 43 + {data.sources && data.sources.length > 0 && ( 44 + <div className="mt-2"> 45 + <p className="font-medium text-sm">Sources:</p> 46 + <ul className="text-sm"> 47 + {data.sources.map((source: { source: string; count: number }) => ( 48 + <li key={source.source}> 49 + {source.source}: {source.count} 50 + </li> 51 + ))} 52 + </ul> 53 + </div> 54 + )} 55 + </div> 56 + ); 57 + } 58 + return null; 59 + }; 60 + 23 61 export function StatisticsModal({ isOpen, onClose, linkId }: StatisticsModalProps) { 24 - const [clicksOverTime, setClicksOverTime] = useState<ClickStats[]>([]); 25 - const [sourcesData, setSourcesData] = useState<SourceStats[]>([]); 26 - const [loading, setLoading] = useState(true); 62 + const [clicksOverTime, setClicksOverTime] = useState<EnhancedClickStats[]>([]); 63 + const [sourcesData, setSourcesData] = useState<SourceStats[]>([]); 64 + const [loading, setLoading] = useState(true); 27 65 28 - useEffect(() => { 29 - if (isOpen && linkId) { 30 - const fetchData = async () => { 31 - try { 32 - setLoading(true); 33 - const [clicksData, sourcesData] = await Promise.all([ 34 - getLinkClickStats(linkId), 35 - getLinkSourceStats(linkId), 36 - ]); 37 - setClicksOverTime(clicksData); 38 - setSourcesData(sourcesData); 39 - } catch (error) { 40 - console.error("Failed to fetch statistics:", error); 41 - } finally { 42 - setLoading(false); 43 - } 44 - }; 66 + useEffect(() => { 67 + if (isOpen && linkId) { 68 + const fetchData = async () => { 69 + try { 70 + setLoading(true); 71 + const [clicksData, sourcesData] = await Promise.all([ 72 + getLinkClickStats(linkId), 73 + getLinkSourceStats(linkId), 74 + ]); 45 75 46 - fetchData(); 47 - } 48 - }, [isOpen, linkId]); 76 + // Enhance clicks data with source information 77 + const enhancedClicksData = clicksData.map((clickData) => ({ 78 + ...clickData, 79 + sources: sourcesData.filter((source) => source.date === clickData.date), 80 + })); 49 81 50 - return ( 51 - <Dialog open={isOpen} onOpenChange={onClose}> 52 - <DialogContent className="max-w-3xl"> 53 - <DialogHeader> 54 - <DialogTitle>Link Statistics</DialogTitle> 55 - </DialogHeader> 82 + setClicksOverTime(enhancedClicksData); 83 + setSourcesData(sourcesData); 84 + } catch (error: unknown) { 85 + console.error("Failed to fetch statistics:", error); 86 + toast({ 87 + variant: "destructive", 88 + title: "Error", 89 + description: error instanceof Error ? error.message : "Failed to load statistics", 90 + }); 91 + } finally { 92 + setLoading(false); 93 + } 94 + }; 56 95 57 - {loading ? ( 58 - <div className="flex items-center justify-center h-64">Loading...</div> 59 - ) : ( 60 - <div className="grid gap-4"> 61 - <Card> 62 - <CardHeader> 63 - <CardTitle>Clicks Over Time</CardTitle> 64 - </CardHeader> 65 - <CardContent> 66 - <div className="h-[300px]"> 67 - <ResponsiveContainer width="100%" height="100%"> 68 - <LineChart data={clicksOverTime}> 69 - <CartesianGrid strokeDasharray="3 3" /> 70 - <XAxis dataKey="date" /> 71 - <YAxis /> 72 - <Tooltip /> 73 - <Line 74 - type="monotone" 75 - dataKey="clicks" 76 - stroke="#8884d8" 77 - strokeWidth={2} 78 - /> 79 - </LineChart> 80 - </ResponsiveContainer> 81 - </div> 82 - </CardContent> 83 - </Card> 96 + fetchData(); 97 + } 98 + }, [isOpen, linkId]); 84 99 85 - <Card> 86 - <CardHeader> 87 - <CardTitle>Top Sources</CardTitle> 88 - </CardHeader> 89 - <CardContent> 90 - <ul className="space-y-2"> 91 - {sourcesData.map((source, index) => ( 92 - <li 93 - key={source.source} 94 - className="flex items-center justify-between py-2 border-b last:border-0" 95 - > 96 - <span className="text-sm"> 97 - <span className="font-medium text-muted-foreground mr-2"> 98 - {index + 1}. 99 - </span> 100 - {source.source} 101 - </span> 102 - <span className="text-sm font-medium"> 103 - {source.count} clicks 104 - </span> 105 - </li> 106 - ))} 107 - </ul> 108 - </CardContent> 109 - </Card> 110 - </div> 111 - )} 112 - </DialogContent> 113 - </Dialog> 100 + const aggregatedSources = useMemo(() => { 101 + const sourceMap = sourcesData.reduce<Record<string, number>>( 102 + (acc, { source, count }) => ({ 103 + ...acc, 104 + [source]: (acc[source] || 0) + count 105 + }), 106 + {} 114 107 ); 108 + 109 + return Object.entries(sourceMap) 110 + .map(([source, count]) => ({ source, count })) 111 + .sort((a, b) => b.count - a.count); 112 + }, [sourcesData]); 113 + 114 + return ( 115 + <Dialog open={isOpen} onOpenChange={onClose}> 116 + <DialogContent className="max-w-3xl"> 117 + <DialogHeader> 118 + <DialogTitle>Link Statistics</DialogTitle> 119 + </DialogHeader> 120 + 121 + {loading ? ( 122 + <div className="flex items-center justify-center h-64">Loading...</div> 123 + ) : ( 124 + <div className="grid gap-4"> 125 + <Card> 126 + <CardHeader> 127 + <CardTitle>Clicks Over Time</CardTitle> 128 + </CardHeader> 129 + <CardContent> 130 + <div className="h-[300px]"> 131 + <ResponsiveContainer width="100%" height="100%"> 132 + <LineChart data={clicksOverTime}> 133 + <CartesianGrid strokeDasharray="3 3" /> 134 + <XAxis dataKey="date" /> 135 + <YAxis /> 136 + <Tooltip content={<CustomTooltip />} /> 137 + <Line 138 + type="monotone" 139 + dataKey="clicks" 140 + stroke="#8884d8" 141 + strokeWidth={2} 142 + /> 143 + </LineChart> 144 + </ResponsiveContainer> 145 + </div> 146 + </CardContent> 147 + </Card> 148 + 149 + <Card> 150 + <CardHeader> 151 + <CardTitle>Top Sources</CardTitle> 152 + </CardHeader> 153 + <CardContent> 154 + <ul className="space-y-2"> 155 + {aggregatedSources.map((source, index) => ( 156 + <li 157 + key={source.source} 158 + className="flex items-center justify-between py-2 border-b last:border-0" 159 + > 160 + <span className="text-sm"> 161 + <span className="font-medium text-muted-foreground mr-2"> 162 + {index + 1}. 163 + </span> 164 + {source.source} 165 + </span> 166 + <span className="text-sm font-medium">{source.count} clicks</span> 167 + </li> 168 + ))} 169 + </ul> 170 + </CardContent> 171 + </Card> 172 + </div> 173 + )} 174 + </DialogContent> 175 + </Dialog> 176 + ); 115 177 }
+10
frontend/src/context/AuthContext.tsx
··· 23 23 setUser(userData); 24 24 } 25 25 setIsLoading(false); 26 + 27 + const handleUnauthorized = () => { 28 + setUser(null); 29 + }; 30 + 31 + window.addEventListener('unauthorized', handleUnauthorized); 32 + 33 + return () => { 34 + window.removeEventListener('unauthorized', handleUnauthorized); 35 + }; 26 36 }, []); 27 37 28 38 const login = async (email: string, password: string) => {
+1
frontend/src/types/api.ts
··· 32 32 } 33 33 34 34 export interface SourceStats { 35 + date: string; 35 36 source: string; 36 37 count: number; 37 38 }
+28 -15
frontend/vite.config.ts
··· 3 3 import tailwindcss from '@tailwindcss/vite' 4 4 import path from "path" 5 5 6 - export default defineConfig(() => ({ 7 - plugins: [react(), tailwindcss()], 8 - server: { 9 - proxy: { 10 - '/api': { 11 - target: process.env.VITE_API_URL || 'http://localhost:8080', 12 - changeOrigin: true, 6 + export default defineConfig(({ command }) => { 7 + if (command === 'serve') { //command == 'dev' 8 + return { 9 + server: { 10 + proxy: { 11 + '/api': { 12 + target: process.env.VITE_API_URL || 'http://localhost:8080', 13 + changeOrigin: true, 14 + }, 15 + }, 16 + }, 17 + plugins: [react(), tailwindcss()], 18 + resolve: { 19 + alias: { 20 + "@": path.resolve(__dirname, "./src"), 21 + }, 22 + }, 23 + } 24 + } else { //command === 'build' 25 + return { 26 + plugins: [react(), tailwindcss()], 27 + resolve: { 28 + alias: { 29 + "@": path.resolve(__dirname, "./src"), 30 + }, 13 31 }, 14 - }, 15 - }, 16 - resolve: { 17 - alias: { 18 - "@": path.resolve(__dirname, "./src"), 19 - }, 20 - }, 21 - })) 32 + } 33 + } 34 + })
+3
migrations/20250219000000_extend_short_code.sql
··· 1 + -- PostgreSQL migration 2 + ALTER TABLE links ALTER COLUMN short_code TYPE VARCHAR(32); 3 +
+42
migrations/sqlite/20250125000000_init.sql
··· 1 + -- Enable foreign key support 2 + PRAGMA foreign_keys = ON; 3 + 4 + -- Add Migration Version 5 + CREATE TABLE IF NOT EXISTS _sqlx_migrations ( 6 + version INTEGER PRIMARY KEY, 7 + description TEXT NOT NULL, 8 + installed_on TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP 9 + ); 10 + 11 + -- Create users table 12 + CREATE TABLE users ( 13 + id INTEGER PRIMARY KEY AUTOINCREMENT, 14 + email VARCHAR(255) NOT NULL UNIQUE, 15 + password_hash TEXT NOT NULL 16 + ); 17 + 18 + -- Create links table 19 + CREATE TABLE links ( 20 + id INTEGER PRIMARY KEY AUTOINCREMENT, 21 + original_url TEXT NOT NULL, 22 + short_code VARCHAR(8) NOT NULL UNIQUE, 23 + created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, 24 + clicks INTEGER NOT NULL DEFAULT 0, 25 + user_id INTEGER, 26 + FOREIGN KEY (user_id) REFERENCES users(id) 27 + ); 28 + 29 + -- Create clicks table 30 + CREATE TABLE clicks ( 31 + id INTEGER PRIMARY KEY AUTOINCREMENT, 32 + link_id INTEGER, 33 + source TEXT, 34 + query_source TEXT, 35 + created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, 36 + FOREIGN KEY (link_id) REFERENCES links(id) 37 + ); 38 + 39 + -- Create indexes 40 + CREATE INDEX idx_short_code ON links(short_code); 41 + CREATE INDEX idx_user_id ON links(user_id); 42 + CREATE INDEX idx_link_id ON clicks(link_id);
readme_img/mainview.jpg

This is a binary file and will not be displayed.

readme_img/statview.jpg

This is a binary file and will not be displayed.

+8 -7
src/auth.rs
··· 1 + use crate::{error::AppError, models::Claims}; 1 2 use actix_web::{dev::Payload, FromRequest, HttpRequest}; 2 3 use jsonwebtoken::{decode, DecodingKey, Validation}; 3 4 use std::future::{ready, Ready}; 4 - use crate::{error::AppError, models::Claims}; 5 5 6 6 pub struct AuthenticatedUser { 7 7 pub user_id: i32, ··· 12 12 type Future = Ready<Result<Self, Self::Error>>; 13 13 14 14 fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future { 15 - let auth_header = req.headers() 15 + let auth_header = req 16 + .headers() 16 17 .get("Authorization") 17 18 .and_then(|h| h.to_str().ok()); 18 19 19 20 if let Some(auth_header) = auth_header { 20 21 if auth_header.starts_with("Bearer ") { 21 22 let token = &auth_header[7..]; 22 - let secret = std::env::var("JWT_SECRET").unwrap_or_else(|_| "default_secret".to_string()); 23 - 23 + let secret = 24 + std::env::var("JWT_SECRET").unwrap_or_else(|_| "default_secret".to_string()); 24 25 match decode::<Claims>( 25 26 token, 26 27 &DecodingKey::from_secret(secret.as_bytes()), 27 - &Validation::default() 28 + &Validation::default(), 28 29 ) { 29 30 Ok(token_data) => { 30 31 return ready(Ok(AuthenticatedUser { ··· 35 36 } 36 37 } 37 38 } 38 - 39 39 ready(Err(AppError::Unauthorized)) 40 40 } 41 - } 41 + } 42 +
+583 -155
src/handlers.rs
··· 2 2 use crate::{ 3 3 error::AppError, 4 4 models::{ 5 - AuthResponse, Claims, ClickStats, CreateLink, Link, LoginRequest, RegisterRequest, 6 - SourceStats, User, UserResponse, 5 + AuthResponse, Claims, ClickStats, CreateLink, DatabasePool, Link, LoginRequest, 6 + RegisterRequest, SourceStats, User, UserResponse, 7 7 }, 8 8 AppState, 9 9 }; ··· 16 16 use jsonwebtoken::{encode, EncodingKey, Header}; 17 17 use lazy_static::lazy_static; 18 18 use regex::Regex; 19 + use serde_json::json; 20 + use sqlx::{Postgres, Sqlite}; 19 21 20 22 lazy_static! { 21 23 static ref VALID_CODE_REGEX: Regex = Regex::new(r"^[a-zA-Z0-9_-]{1,32}$").unwrap(); ··· 27 29 payload: web::Json<CreateLink>, 28 30 ) -> Result<impl Responder, AppError> { 29 31 tracing::debug!("Creating short URL with user_id: {}", user.user_id); 30 - 31 32 validate_url(&payload.url)?; 32 33 33 34 let short_code = if let Some(ref custom_code) = payload.custom_code { 34 35 validate_custom_code(custom_code)?; 35 36 36 - tracing::debug!("Checking if custom code {} exists", custom_code); 37 - // Check if code is already taken 38 - if let Some(_) = sqlx::query_as::<_, Link>("SELECT * FROM links WHERE short_code = $1") 39 - .bind(custom_code) 40 - .fetch_optional(&state.db) 41 - .await? 42 - { 37 + // Check if code exists using match on pool type 38 + let exists = match &state.db { 39 + DatabasePool::Postgres(pool) => { 40 + sqlx::query_as::<_, Link>("SELECT * FROM links WHERE short_code = $1") 41 + .bind(custom_code) 42 + .fetch_optional(pool) 43 + .await? 44 + } 45 + DatabasePool::Sqlite(pool) => { 46 + sqlx::query_as::<_, Link>("SELECT * FROM links WHERE short_code = ?1") 47 + .bind(custom_code) 48 + .fetch_optional(pool) 49 + .await? 50 + } 51 + }; 52 + 53 + if exists.is_some() { 43 54 return Err(AppError::InvalidInput( 44 55 "Custom code already taken".to_string(), 45 56 )); 46 57 } 47 - 48 58 custom_code.clone() 49 59 } else { 50 60 generate_short_code() 51 61 }; 52 62 53 - // Start transaction 54 - let mut tx = state.db.begin().await?; 63 + // Start transaction based on pool type 64 + let result = match &state.db { 65 + DatabasePool::Postgres(pool) => { 66 + let mut tx = pool.begin().await?; 67 + 68 + let link = sqlx::query_as::<_, Link>( 69 + "INSERT INTO links (original_url, short_code, user_id) VALUES ($1, $2, $3) RETURNING *" 70 + ) 71 + .bind(&payload.url) 72 + .bind(&short_code) 73 + .bind(user.user_id) 74 + .fetch_one(&mut *tx) 75 + .await?; 76 + 77 + if let Some(ref source) = payload.source { 78 + sqlx::query("INSERT INTO clicks (link_id, source) VALUES ($1, $2)") 79 + .bind(link.id) 80 + .bind(source) 81 + .execute(&mut *tx) 82 + .await?; 83 + } 55 84 56 - tracing::debug!("Inserting new link with short_code: {}", short_code); 57 - let link = sqlx::query_as::<_, Link>( 58 - "INSERT INTO links (original_url, short_code, user_id) VALUES ($1, $2, $3) RETURNING *", 59 - ) 60 - .bind(&payload.url) 61 - .bind(&short_code) 62 - .bind(user.user_id) 63 - .fetch_one(&mut *tx) 64 - .await?; 85 + tx.commit().await?; 86 + link 87 + } 88 + DatabasePool::Sqlite(pool) => { 89 + let mut tx = pool.begin().await?; 65 90 66 - if let Some(ref source) = payload.source { 67 - tracing::debug!("Adding click source: {}", source); 68 - sqlx::query("INSERT INTO clicks (link_id, source) VALUES ($1, $2)") 69 - .bind(link.id) 70 - .bind(source) 71 - .execute(&mut *tx) 91 + let link = sqlx::query_as::<_, Link>( 92 + "INSERT INTO links (original_url, short_code, user_id) VALUES (?1, ?2, ?3) RETURNING *" 93 + ) 94 + .bind(&payload.url) 95 + .bind(&short_code) 96 + .bind(user.user_id) 97 + .fetch_one(&mut *tx) 72 98 .await?; 73 - } 99 + 100 + if let Some(ref source) = payload.source { 101 + sqlx::query("INSERT INTO clicks (link_id, source) VALUES (?1, ?2)") 102 + .bind(link.id) 103 + .bind(source) 104 + .execute(&mut *tx) 105 + .await?; 106 + } 107 + 108 + tx.commit().await?; 109 + link 110 + } 111 + }; 74 112 75 - tx.commit().await?; 76 - Ok(HttpResponse::Created().json(link)) 113 + Ok(HttpResponse::Created().json(result)) 77 114 } 78 115 79 116 fn validate_custom_code(code: &str) -> Result<(), AppError> { ··· 94 131 Ok(()) 95 132 } 96 133 97 - fn validate_url(url: &String) -> Result<(), AppError> { 134 + fn validate_url(url: &str) -> Result<(), AppError> { 98 135 if url.is_empty() { 99 136 return Err(AppError::InvalidInput("URL cannot be empty".to_string())); 100 137 } ··· 120 157 .and_then(|q| web::Query::<std::collections::HashMap<String, String>>::from_query(q).ok()) 121 158 .and_then(|params| params.get("source").cloned()); 122 159 123 - let mut tx = state.db.begin().await?; 124 - 125 - let link = sqlx::query_as::<_, Link>( 126 - "UPDATE links SET clicks = clicks + 1 WHERE short_code = $1 RETURNING *", 127 - ) 128 - .bind(&short_code) 129 - .fetch_optional(&mut *tx) 130 - .await?; 160 + let link = match &state.db { 161 + DatabasePool::Postgres(pool) => { 162 + let mut tx = pool.begin().await?; 163 + let link = sqlx::query_as::<_, Link>( 164 + "UPDATE links SET clicks = clicks + 1 WHERE short_code = $1 RETURNING *", 165 + ) 166 + .bind(&short_code) 167 + .fetch_optional(&mut *tx) 168 + .await?; 169 + tx.commit().await?; 170 + link 171 + } 172 + DatabasePool::Sqlite(pool) => { 173 + let mut tx = pool.begin().await?; 174 + let link = sqlx::query_as::<_, Link>( 175 + "UPDATE links SET clicks = clicks + 1 WHERE short_code = ?1 RETURNING *", 176 + ) 177 + .bind(&short_code) 178 + .fetch_optional(&mut *tx) 179 + .await?; 180 + tx.commit().await?; 181 + link 182 + } 183 + }; 131 184 132 185 match link { 133 186 Some(link) => { 134 - // Record click with both user agent and query source 135 - let user_agent = req 136 - .headers() 137 - .get("user-agent") 138 - .and_then(|h| h.to_str().ok()) 139 - .unwrap_or("unknown") 140 - .to_string(); 187 + // Handle click recording based on database type 188 + match &state.db { 189 + DatabasePool::Postgres(pool) => { 190 + let mut tx = pool.begin().await?; 191 + let user_agent = req 192 + .headers() 193 + .get("user-agent") 194 + .and_then(|h| h.to_str().ok()) 195 + .unwrap_or("unknown") 196 + .to_string(); 141 197 142 - sqlx::query("INSERT INTO clicks (link_id, source, query_source) VALUES ($1, $2, $3)") 143 - .bind(link.id) 144 - .bind(user_agent) 145 - .bind(query_source) 146 - .execute(&mut *tx) 147 - .await?; 198 + sqlx::query( 199 + "INSERT INTO clicks (link_id, source, query_source) VALUES ($1, $2, $3)", 200 + ) 201 + .bind(link.id) 202 + .bind(user_agent) 203 + .bind(query_source) 204 + .execute(&mut *tx) 205 + .await?; 148 206 149 - tx.commit().await?; 207 + tx.commit().await?; 208 + } 209 + DatabasePool::Sqlite(pool) => { 210 + let mut tx = pool.begin().await?; 211 + let user_agent = req 212 + .headers() 213 + .get("user-agent") 214 + .and_then(|h| h.to_str().ok()) 215 + .unwrap_or("unknown") 216 + .to_string(); 217 + 218 + sqlx::query( 219 + "INSERT INTO clicks (link_id, source, query_source) VALUES (?1, ?2, ?3)", 220 + ) 221 + .bind(link.id) 222 + .bind(user_agent) 223 + .bind(query_source) 224 + .execute(&mut *tx) 225 + .await?; 226 + 227 + tx.commit().await?; 228 + } 229 + }; 150 230 151 231 Ok(HttpResponse::TemporaryRedirect() 152 232 .append_header(("Location", link.original_url)) ··· 160 240 state: web::Data<AppState>, 161 241 user: AuthenticatedUser, 162 242 ) -> Result<impl Responder, AppError> { 163 - let links = sqlx::query_as::<_, Link>( 164 - "SELECT * FROM links WHERE user_id = $1 ORDER BY created_at DESC", 165 - ) 166 - .bind(user.user_id) 167 - .fetch_all(&state.db) 168 - .await?; 243 + let links = match &state.db { 244 + DatabasePool::Postgres(pool) => { 245 + sqlx::query_as::<_, Link>( 246 + "SELECT * FROM links WHERE user_id = $1 ORDER BY created_at DESC", 247 + ) 248 + .bind(user.user_id) 249 + .fetch_all(pool) 250 + .await? 251 + } 252 + DatabasePool::Sqlite(pool) => { 253 + sqlx::query_as::<_, Link>( 254 + "SELECT * FROM links WHERE user_id = ?1 ORDER BY created_at DESC", 255 + ) 256 + .bind(user.user_id) 257 + .fetch_all(pool) 258 + .await? 259 + } 260 + }; 169 261 170 262 Ok(HttpResponse::Ok().json(links)) 171 263 } 172 264 173 265 pub async fn health_check(state: web::Data<AppState>) -> impl Responder { 174 - match sqlx::query("SELECT 1").execute(&state.db).await { 175 - Ok(_) => HttpResponse::Ok().json("Healthy"), 176 - Err(_) => HttpResponse::ServiceUnavailable().json("Database unavailable"), 266 + let is_healthy = match &state.db { 267 + DatabasePool::Postgres(pool) => sqlx::query("SELECT 1").execute(pool).await.is_ok(), 268 + DatabasePool::Sqlite(pool) => sqlx::query("SELECT 1").execute(pool).await.is_ok(), 269 + }; 270 + 271 + if is_healthy { 272 + HttpResponse::Ok().json("Healthy") 273 + } else { 274 + HttpResponse::ServiceUnavailable().json("Database unavailable") 177 275 } 178 276 } 179 277 ··· 190 288 payload: web::Json<RegisterRequest>, 191 289 ) -> Result<impl Responder, AppError> { 192 290 // Check if any users exist 193 - let user_count = sqlx::query!("SELECT COUNT(*) as count FROM users") 194 - .fetch_one(&state.db) 195 - .await? 196 - .count 197 - .unwrap_or(0); 291 + let user_count = match &state.db { 292 + DatabasePool::Postgres(pool) => { 293 + let mut tx = pool.begin().await?; 294 + let count = sqlx::query_as::<Postgres, (i64,)>("SELECT COUNT(*)::bigint FROM users") 295 + .fetch_one(&mut *tx) 296 + .await? 297 + .0; 298 + tx.commit().await?; 299 + count 300 + } 301 + DatabasePool::Sqlite(pool) => { 302 + let mut tx = pool.begin().await?; 303 + let count = sqlx::query_as::<Sqlite, (i64,)>("SELECT COUNT(*) FROM users") 304 + .fetch_one(&mut *tx) 305 + .await? 306 + .0; 307 + tx.commit().await?; 308 + count 309 + } 310 + }; 198 311 199 312 // If users exist, registration is closed - no exceptions 200 313 if user_count > 0 { ··· 210 323 } 211 324 212 325 // Check if email already exists 213 - let exists = sqlx::query!("SELECT id FROM users WHERE email = $1", payload.email) 214 - .fetch_optional(&state.db) 215 - .await?; 326 + let exists = match &state.db { 327 + DatabasePool::Postgres(pool) => { 328 + let mut tx = pool.begin().await?; 329 + let exists = 330 + sqlx::query_as::<Postgres, (i32,)>("SELECT id FROM users WHERE email = $1") 331 + .bind(&payload.email) 332 + .fetch_optional(&mut *tx) 333 + .await?; 334 + tx.commit().await?; 335 + exists 336 + } 337 + DatabasePool::Sqlite(pool) => { 338 + let mut tx = pool.begin().await?; 339 + let exists = sqlx::query_as::<Sqlite, (i32,)>("SELECT id FROM users WHERE email = ?") 340 + .bind(&payload.email) 341 + .fetch_optional(&mut *tx) 342 + .await?; 343 + tx.commit().await?; 344 + exists 345 + } 346 + }; 216 347 217 348 if exists.is_some() { 218 349 return Err(AppError::Auth("Email already registered".to_string())); ··· 225 356 .map_err(|e| AppError::Auth(e.to_string()))? 226 357 .to_string(); 227 358 228 - let user = sqlx::query_as!( 229 - User, 230 - "INSERT INTO users (email, password_hash) VALUES ($1, $2) RETURNING *", 231 - payload.email, 232 - password_hash 233 - ) 234 - .fetch_one(&state.db) 235 - .await?; 359 + // Insert new user 360 + let user = match &state.db { 361 + DatabasePool::Postgres(pool) => { 362 + let mut tx = pool.begin().await?; 363 + let user = sqlx::query_as::<Postgres, User>( 364 + "INSERT INTO users (email, password_hash) VALUES ($1, $2) RETURNING *", 365 + ) 366 + .bind(&payload.email) 367 + .bind(&password_hash) 368 + .fetch_one(&mut *tx) 369 + .await?; 370 + tx.commit().await?; 371 + user 372 + } 373 + DatabasePool::Sqlite(pool) => { 374 + let mut tx = pool.begin().await?; 375 + let user = sqlx::query_as::<Sqlite, User>( 376 + "INSERT INTO users (email, password_hash) VALUES (?, ?) RETURNING *", 377 + ) 378 + .bind(&payload.email) 379 + .bind(&password_hash) 380 + .fetch_one(&mut *tx) 381 + .await?; 382 + tx.commit().await?; 383 + user 384 + } 385 + }; 236 386 237 387 let claims = Claims::new(user.id); 238 388 let secret = std::env::var("JWT_SECRET").unwrap_or_else(|_| "default_secret".to_string()); ··· 256 406 state: web::Data<AppState>, 257 407 payload: web::Json<LoginRequest>, 258 408 ) -> Result<impl Responder, AppError> { 259 - let user = sqlx::query_as!(User, "SELECT * FROM users WHERE email = $1", payload.email) 260 - .fetch_optional(&state.db) 261 - .await? 262 - .ok_or_else(|| AppError::Auth("Invalid credentials".to_string()))?; 409 + let user = match &state.db { 410 + DatabasePool::Postgres(pool) => { 411 + let mut tx = pool.begin().await?; 412 + let user = sqlx::query_as::<Postgres, User>("SELECT * FROM users WHERE email = $1") 413 + .bind(&payload.email) 414 + .fetch_optional(&mut *tx) 415 + .await?; 416 + tx.commit().await?; 417 + user 418 + } 419 + DatabasePool::Sqlite(pool) => { 420 + let mut tx = pool.begin().await?; 421 + let user = sqlx::query_as::<Sqlite, User>("SELECT * FROM users WHERE email = ?") 422 + .bind(&payload.email) 423 + .fetch_optional(&mut *tx) 424 + .await?; 425 + tx.commit().await?; 426 + user 427 + } 428 + } 429 + .ok_or_else(|| AppError::Auth("Invalid credentials".to_string()))?; 263 430 264 431 let argon2 = Argon2::default(); 265 432 let parsed_hash = ··· 290 457 })) 291 458 } 292 459 293 - pub async fn delete_link( 460 + pub async fn edit_link( 294 461 state: web::Data<AppState>, 295 462 user: AuthenticatedUser, 296 463 path: web::Path<i32>, 464 + payload: web::Json<CreateLink>, 297 465 ) -> Result<impl Responder, AppError> { 298 - let link_id = path.into_inner(); 466 + let link_id: i32 = path.into_inner(); 299 467 300 - // Start transaction 301 - let mut tx = state.db.begin().await?; 468 + // Validate the new URL if provided 469 + validate_url(&payload.url)?; 302 470 303 - // Verify the link belongs to the user 304 - let link = sqlx::query!( 305 - "SELECT id FROM links WHERE id = $1 AND user_id = $2", 306 - link_id, 307 - user.user_id 308 - ) 309 - .fetch_optional(&mut *tx) 310 - .await?; 471 + // Validate custom code if provided 472 + if let Some(ref custom_code) = payload.custom_code { 473 + validate_custom_code(custom_code)?; 311 474 312 - if link.is_none() { 313 - return Err(AppError::NotFound); 475 + // Check if the custom code is already taken by another link 476 + let existing_link = match &state.db { 477 + DatabasePool::Postgres(pool) => { 478 + sqlx::query_as::<_, Link>("SELECT * FROM links WHERE short_code = $1 AND id != $2") 479 + .bind(custom_code) 480 + .bind(link_id) 481 + .fetch_optional(pool) 482 + .await? 483 + } 484 + DatabasePool::Sqlite(pool) => { 485 + sqlx::query_as::<_, Link>("SELECT * FROM links WHERE short_code = ?1 AND id != ?2") 486 + .bind(custom_code) 487 + .bind(link_id) 488 + .fetch_optional(pool) 489 + .await? 490 + } 491 + }; 492 + 493 + if existing_link.is_some() { 494 + return Err(AppError::InvalidInput( 495 + "Custom code already taken".to_string(), 496 + )); 497 + } 314 498 } 315 499 316 - // Delete associated clicks first due to foreign key constraint 317 - sqlx::query!("DELETE FROM clicks WHERE link_id = $1", link_id) 318 - .execute(&mut *tx) 319 - .await?; 500 + // Update the link 501 + let updated_link = match &state.db { 502 + DatabasePool::Postgres(pool) => { 503 + let mut tx = pool.begin().await?; 504 + 505 + // First verify the link belongs to the user 506 + let link = 507 + sqlx::query_as::<_, Link>("SELECT * FROM links WHERE id = $1 AND user_id = $2") 508 + .bind(link_id) 509 + .bind(user.user_id) 510 + .fetch_optional(&mut *tx) 511 + .await?; 512 + 513 + if link.is_none() { 514 + return Err(AppError::NotFound); 515 + } 516 + 517 + // Update the link 518 + let updated = sqlx::query_as::<_, Link>( 519 + r#" 520 + UPDATE links 521 + SET 522 + original_url = $1, 523 + short_code = COALESCE($2, short_code) 524 + WHERE id = $3 AND user_id = $4 525 + RETURNING * 526 + "#, 527 + ) 528 + .bind(&payload.url) 529 + .bind(&payload.custom_code) 530 + .bind(link_id) 531 + .bind(user.user_id) 532 + .fetch_one(&mut *tx) 533 + .await?; 534 + 535 + // If source is provided, add a click record 536 + if let Some(ref source) = payload.source { 537 + sqlx::query("INSERT INTO clicks (link_id, source) VALUES ($1, $2)") 538 + .bind(link_id) 539 + .bind(source) 540 + .execute(&mut *tx) 541 + .await?; 542 + } 543 + 544 + tx.commit().await?; 545 + updated 546 + } 547 + DatabasePool::Sqlite(pool) => { 548 + let mut tx = pool.begin().await?; 549 + 550 + // First verify the link belongs to the user 551 + let link = 552 + sqlx::query_as::<_, Link>("SELECT * FROM links WHERE id = ?1 AND user_id = ?2") 553 + .bind(link_id) 554 + .bind(user.user_id) 555 + .fetch_optional(&mut *tx) 556 + .await?; 557 + 558 + if link.is_none() { 559 + return Err(AppError::NotFound); 560 + } 561 + 562 + // Update the link 563 + let updated = sqlx::query_as::<_, Link>( 564 + r#" 565 + UPDATE links 566 + SET 567 + original_url = ?1, 568 + short_code = COALESCE(?2, short_code) 569 + WHERE id = ?3 AND user_id = ?4 570 + RETURNING * 571 + "#, 572 + ) 573 + .bind(&payload.url) 574 + .bind(&payload.custom_code) 575 + .bind(link_id) 576 + .bind(user.user_id) 577 + .fetch_one(&mut *tx) 578 + .await?; 579 + 580 + // If source is provided, add a click record 581 + if let Some(ref source) = payload.source { 582 + sqlx::query("INSERT INTO clicks (link_id, source) VALUES (?1, ?2)") 583 + .bind(link_id) 584 + .bind(source) 585 + .execute(&mut *tx) 586 + .await?; 587 + } 320 588 321 - // Delete the link 322 - sqlx::query!("DELETE FROM links WHERE id = $1", link_id) 323 - .execute(&mut *tx) 324 - .await?; 589 + tx.commit().await?; 590 + updated 591 + } 592 + }; 325 593 326 - tx.commit().await?; 594 + Ok(HttpResponse::Ok().json(updated_link)) 595 + } 596 + 597 + pub async fn delete_link( 598 + state: web::Data<AppState>, 599 + user: AuthenticatedUser, 600 + path: web::Path<i32>, 601 + ) -> Result<impl Responder, AppError> { 602 + let link_id: i32 = path.into_inner(); 603 + 604 + match &state.db { 605 + DatabasePool::Postgres(pool) => { 606 + let mut tx = pool.begin().await?; 607 + 608 + // Verify the link belongs to the user 609 + let link = sqlx::query_as::<Postgres, (i32,)>( 610 + "SELECT id FROM links WHERE id = $1 AND user_id = $2", 611 + ) 612 + .bind(link_id) 613 + .bind(user.user_id) 614 + .fetch_optional(&mut *tx) 615 + .await?; 616 + 617 + if link.is_none() { 618 + return Err(AppError::NotFound); 619 + } 620 + 621 + // Delete associated clicks first due to foreign key constraint 622 + sqlx::query("DELETE FROM clicks WHERE link_id = $1") 623 + .bind(link_id) 624 + .execute(&mut *tx) 625 + .await?; 626 + 627 + // Delete the link 628 + sqlx::query("DELETE FROM links WHERE id = $1") 629 + .bind(link_id) 630 + .execute(&mut *tx) 631 + .await?; 632 + 633 + tx.commit().await?; 634 + } 635 + DatabasePool::Sqlite(pool) => { 636 + let mut tx = pool.begin().await?; 637 + 638 + // Verify the link belongs to the user 639 + let link = sqlx::query_as::<Sqlite, (i32,)>( 640 + "SELECT id FROM links WHERE id = ? AND user_id = ?", 641 + ) 642 + .bind(link_id) 643 + .bind(user.user_id) 644 + .fetch_optional(&mut *tx) 645 + .await?; 646 + 647 + if link.is_none() { 648 + return Err(AppError::NotFound); 649 + } 650 + 651 + // Delete associated clicks first due to foreign key constraint 652 + sqlx::query("DELETE FROM clicks WHERE link_id = ?") 653 + .bind(link_id) 654 + .execute(&mut *tx) 655 + .await?; 656 + 657 + // Delete the link 658 + sqlx::query("DELETE FROM links WHERE id = ?") 659 + .bind(link_id) 660 + .execute(&mut *tx) 661 + .await?; 662 + 663 + tx.commit().await?; 664 + } 665 + } 327 666 328 667 Ok(HttpResponse::NoContent().finish()) 329 668 } ··· 335 674 ) -> Result<impl Responder, AppError> { 336 675 let link_id = path.into_inner(); 337 676 338 - // Verify the link belongs to the user 339 - let link = sqlx::query!( 340 - "SELECT id FROM links WHERE id = $1 AND user_id = $2", 341 - link_id, 342 - user.user_id 343 - ) 344 - .fetch_optional(&state.db) 345 - .await?; 677 + // First verify the link belongs to the user 678 + let link = match &state.db { 679 + DatabasePool::Postgres(pool) => { 680 + sqlx::query_as::<_, (i32,)>("SELECT id FROM links WHERE id = $1 AND user_id = $2") 681 + .bind(link_id) 682 + .bind(user.user_id) 683 + .fetch_optional(pool) 684 + .await? 685 + } 686 + DatabasePool::Sqlite(pool) => { 687 + sqlx::query_as::<_, (i32,)>("SELECT id FROM links WHERE id = ? AND user_id = ?") 688 + .bind(link_id) 689 + .bind(user.user_id) 690 + .fetch_optional(pool) 691 + .await? 692 + } 693 + }; 346 694 347 695 if link.is_none() { 348 696 return Err(AppError::NotFound); 349 697 } 350 698 351 - let clicks = sqlx::query_as!( 352 - ClickStats, 353 - r#" 354 - SELECT 355 - DATE(created_at)::date as "date!", 356 - COUNT(*)::bigint as "clicks!" 357 - FROM clicks 358 - WHERE link_id = $1 359 - GROUP BY DATE(created_at) 360 - ORDER BY DATE(created_at) ASC -- Changed from DESC to ASC 361 - LIMIT 30 362 - "#, 363 - link_id 364 - ) 365 - .fetch_all(&state.db) 366 - .await?; 699 + let clicks = match &state.db { 700 + DatabasePool::Postgres(pool) => { 701 + sqlx::query_as::<_, ClickStats>( 702 + r#" 703 + SELECT 704 + DATE(created_at)::text as date, 705 + COUNT(*)::bigint as clicks 706 + FROM clicks 707 + WHERE link_id = $1 708 + GROUP BY DATE(created_at) 709 + ORDER BY DATE(created_at) ASC 710 + "#, 711 + ) 712 + .bind(link_id) 713 + .fetch_all(pool) 714 + .await? 715 + } 716 + DatabasePool::Sqlite(pool) => { 717 + sqlx::query_as::<_, ClickStats>( 718 + r#" 719 + SELECT 720 + DATE(created_at) as date, 721 + COUNT(*) as clicks 722 + FROM clicks 723 + WHERE link_id = ? 724 + GROUP BY DATE(created_at) 725 + ORDER BY DATE(created_at) ASC 726 + "#, 727 + ) 728 + .bind(link_id) 729 + .fetch_all(pool) 730 + .await? 731 + } 732 + }; 367 733 368 734 Ok(HttpResponse::Ok().json(clicks)) 369 735 } ··· 376 742 let link_id = path.into_inner(); 377 743 378 744 // Verify the link belongs to the user 379 - let link = sqlx::query!( 380 - "SELECT id FROM links WHERE id = $1 AND user_id = $2", 381 - link_id, 382 - user.user_id 383 - ) 384 - .fetch_optional(&state.db) 385 - .await?; 745 + let link = match &state.db { 746 + DatabasePool::Postgres(pool) => { 747 + let mut tx = pool.begin().await?; 748 + let link = sqlx::query_as::<Postgres, (i32,)>( 749 + "SELECT id FROM links WHERE id = $1 AND user_id = $2", 750 + ) 751 + .bind(link_id) 752 + .bind(user.user_id) 753 + .fetch_optional(&mut *tx) 754 + .await?; 755 + tx.commit().await?; 756 + link 757 + } 758 + DatabasePool::Sqlite(pool) => { 759 + let mut tx = pool.begin().await?; 760 + let link = sqlx::query_as::<Sqlite, (i32,)>( 761 + "SELECT id FROM links WHERE id = ? AND user_id = ?", 762 + ) 763 + .bind(link_id) 764 + .bind(user.user_id) 765 + .fetch_optional(&mut *tx) 766 + .await?; 767 + tx.commit().await?; 768 + link 769 + } 770 + }; 386 771 387 772 if link.is_none() { 388 773 return Err(AppError::NotFound); 389 774 } 390 775 391 - let sources = sqlx::query_as!( 392 - SourceStats, 393 - r#" 394 - SELECT 395 - query_source as "source!", 396 - COUNT(*)::bigint as "count!" 397 - FROM clicks 398 - WHERE link_id = $1 399 - AND query_source IS NOT NULL 400 - AND query_source != '' 401 - GROUP BY query_source 402 - ORDER BY COUNT(*) DESC 403 - LIMIT 10 404 - "#, 405 - link_id 406 - ) 407 - .fetch_all(&state.db) 408 - .await?; 776 + let sources = match &state.db { 777 + DatabasePool::Postgres(pool) => { 778 + sqlx::query_as::<_, SourceStats>( 779 + r#" 780 + SELECT 781 + DATE(created_at)::text as date, 782 + query_source as source, 783 + COUNT(*)::bigint as count 784 + FROM clicks 785 + WHERE link_id = $1 786 + AND query_source IS NOT NULL 787 + AND query_source != '' 788 + GROUP BY DATE(created_at), query_source 789 + ORDER BY DATE(created_at) ASC, COUNT(*) DESC 790 + "#, 791 + ) 792 + .bind(link_id) 793 + .fetch_all(pool) 794 + .await? 795 + } 796 + DatabasePool::Sqlite(pool) => { 797 + sqlx::query_as::<_, SourceStats>( 798 + r#" 799 + SELECT 800 + DATE(created_at) as date, 801 + query_source as source, 802 + COUNT(*) as count 803 + FROM clicks 804 + WHERE link_id = ? 805 + AND query_source IS NOT NULL 806 + AND query_source != '' 807 + GROUP BY DATE(created_at), query_source 808 + ORDER BY DATE(created_at) ASC, COUNT(*) DESC 809 + "#, 810 + ) 811 + .bind(link_id) 812 + .fetch_all(pool) 813 + .await? 814 + } 815 + }; 409 816 410 817 Ok(HttpResponse::Ok().json(sources)) 411 818 } 819 + 820 + pub async fn check_first_user(state: web::Data<AppState>) -> Result<impl Responder, AppError> { 821 + let user_count = match &state.db { 822 + DatabasePool::Postgres(pool) => { 823 + sqlx::query_as::<Postgres, (i64,)>("SELECT COUNT(*)::bigint FROM users") 824 + .fetch_one(pool) 825 + .await? 826 + .0 827 + } 828 + DatabasePool::Sqlite(pool) => { 829 + sqlx::query_as::<Sqlite, (i64,)>("SELECT COUNT(*) FROM users") 830 + .fetch_one(pool) 831 + .await? 832 + .0 833 + } 834 + }; 835 + 836 + Ok(HttpResponse::Ok().json(json!({ 837 + "isFirstUser": user_count == 0 838 + }))) 839 + }
+94 -10
src/lib.rs
··· 1 + use anyhow::Result; 1 2 use rand::Rng; 2 - use sqlx::PgPool; 3 + use sqlx::migrate::MigrateDatabase; 4 + use sqlx::postgres::PgPoolOptions; 5 + use sqlx::{Postgres, Sqlite}; 3 6 use std::fs::File; 4 7 use std::io::Write; 5 8 use tracing::info; 9 + 10 + use models::DatabasePool; 6 11 7 12 pub mod auth; 8 13 pub mod error; ··· 11 16 12 17 #[derive(Clone)] 13 18 pub struct AppState { 14 - pub db: PgPool, 19 + pub db: DatabasePool, 15 20 pub admin_token: Option<String>, 16 21 } 17 22 18 - pub async fn check_and_generate_admin_token(pool: &sqlx::PgPool) -> anyhow::Result<Option<String>> { 23 + pub async fn create_db_pool() -> Result<DatabasePool> { 24 + let database_url = std::env::var("DATABASE_URL").ok(); 25 + 26 + match database_url { 27 + Some(url) if url.starts_with("postgres://") || url.starts_with("postgresql://") => { 28 + info!("Using PostgreSQL database"); 29 + let pool = PgPoolOptions::new() 30 + .max_connections(5) 31 + .acquire_timeout(std::time::Duration::from_secs(3)) 32 + .connect(&url) 33 + .await?; 34 + 35 + Ok(DatabasePool::Postgres(pool)) 36 + } 37 + _ => { 38 + info!("No PostgreSQL connection string found, using SQLite"); 39 + 40 + // Get the project root directory 41 + let project_root = std::env::current_dir()?; 42 + let data_dir = project_root.join("data"); 43 + 44 + // Create a data directory if it doesn't exist 45 + if !data_dir.exists() { 46 + std::fs::create_dir_all(&data_dir)?; 47 + } 48 + 49 + let db_path = data_dir.join("simplelink.db"); 50 + let sqlite_url = format!("sqlite://{}", db_path.display()); 51 + 52 + // Check if database exists and create it if it doesn't 53 + if !Sqlite::database_exists(&sqlite_url).await.unwrap_or(false) { 54 + info!("Creating new SQLite database at {}", db_path.display()); 55 + Sqlite::create_database(&sqlite_url).await?; 56 + info!("Database created successfully"); 57 + } else { 58 + info!("Database already exists"); 59 + } 60 + 61 + let pool = sqlx::sqlite::SqlitePoolOptions::new() 62 + .max_connections(5) 63 + .connect(&sqlite_url) 64 + .await?; 65 + 66 + Ok(DatabasePool::Sqlite(pool)) 67 + } 68 + } 69 + } 70 + 71 + pub async fn run_migrations(pool: &DatabasePool) -> Result<()> { 72 + match pool { 73 + DatabasePool::Postgres(pool) => { 74 + // Use the root migrations directory for postgres 75 + sqlx::migrate!().run(pool).await?; 76 + } 77 + DatabasePool::Sqlite(pool) => { 78 + sqlx::migrate!("./migrations/sqlite").run(pool).await?; 79 + } 80 + } 81 + Ok(()) 82 + } 83 + 84 + pub async fn check_and_generate_admin_token(db: &DatabasePool) -> anyhow::Result<Option<String>> { 19 85 // Check if any users exist 20 - let user_count = sqlx::query!("SELECT COUNT(*) as count FROM users") 21 - .fetch_one(pool) 22 - .await? 23 - .count 24 - .unwrap_or(0); 86 + let user_count = match db { 87 + DatabasePool::Postgres(pool) => { 88 + let mut tx = pool.begin().await?; 89 + let count = sqlx::query_as::<Postgres, (i64,)>("SELECT COUNT(*)::bigint FROM users") 90 + .fetch_one(&mut *tx) 91 + .await? 92 + .0; 93 + tx.commit().await?; 94 + count 95 + } 96 + DatabasePool::Sqlite(pool) => { 97 + let mut tx = pool.begin().await?; 98 + let count = sqlx::query_as::<Sqlite, (i64,)>("SELECT COUNT(*) FROM users") 99 + .fetch_one(&mut *tx) 100 + .await? 101 + .0; 102 + tx.commit().await?; 103 + count 104 + } 105 + }; 25 106 26 107 if user_count == 0 { 27 - // Generate a random token using simple characters 28 108 let token: String = (0..32) 29 109 .map(|_| { 30 110 let idx = rand::thread_rng().gen_range(0..62); ··· 36 116 }) 37 117 .collect(); 38 118 119 + // Get the project root directory 120 + let project_root = std::env::current_dir()?; 121 + let token_path = project_root.join("admin-setup-token.txt"); 122 + 39 123 // Save token to file 40 - let mut file = File::create("admin-setup-token.txt")?; 124 + let mut file = File::create(token_path)?; 41 125 writeln!(file, "{}", token)?; 42 126 43 127 info!("No users found - generated admin setup token");
+188 -15
src/main.rs
··· 1 1 use actix_cors::Cors; 2 - use actix_files as fs; 3 - use actix_web::{web, App, HttpServer}; 2 + use actix_web::{web, App, HttpResponse, HttpServer}; 4 3 use anyhow::Result; 4 + use clap::Parser; 5 + use rust_embed::RustEmbed; 5 6 use simplelink::check_and_generate_admin_token; 7 + use simplelink::models::DatabasePool; 8 + use simplelink::{create_db_pool, run_migrations}; 6 9 use simplelink::{handlers, AppState}; 7 - use sqlx::postgres::PgPoolOptions; 8 - use tracing::info; 10 + use sqlx::{Postgres, Sqlite}; 11 + use tracing::{error, info}; 12 + 13 + #[derive(Parser, Debug)] 14 + #[command(author, version, about, long_about = None)] 15 + #[derive(RustEmbed)] 16 + #[folder = "static/"] 17 + struct Asset; 18 + 19 + async fn serve_static_file(path: &str) -> HttpResponse { 20 + match Asset::get(path) { 21 + Some(content) => { 22 + let mime = mime_guess::from_path(path).first_or_octet_stream(); 23 + HttpResponse::Ok() 24 + .content_type(mime.as_ref()) 25 + .body(content.data.into_owned()) 26 + } 27 + None => HttpResponse::NotFound().body("404 Not Found"), 28 + } 29 + } 30 + 31 + async fn create_initial_links(pool: &DatabasePool) -> Result<()> { 32 + if let Ok(links) = std::env::var("INITIAL_LINKS") { 33 + for link_entry in links.split(';') { 34 + let parts: Vec<&str> = link_entry.split(',').collect(); 35 + if parts.len() >= 2 { 36 + let url = parts[0]; 37 + let code = parts[1]; 38 + 39 + match pool { 40 + DatabasePool::Postgres(pool) => { 41 + sqlx::query( 42 + "INSERT INTO links (original_url, short_code, user_id) 43 + VALUES ($1, $2, $3) 44 + ON CONFLICT (short_code) 45 + DO UPDATE SET short_code = EXCLUDED.short_code 46 + WHERE links.original_url = EXCLUDED.original_url", 47 + ) 48 + .bind(url) 49 + .bind(code) 50 + .bind(1) 51 + .execute(pool) 52 + .await?; 53 + } 54 + DatabasePool::Sqlite(pool) => { 55 + // First check if the exact combination exists 56 + let exists = sqlx::query_scalar::<_, bool>( 57 + "SELECT EXISTS( 58 + SELECT 1 FROM links 59 + WHERE original_url = ?1 60 + AND short_code = ?2 61 + )", 62 + ) 63 + .bind(url) 64 + .bind(code) 65 + .fetch_one(pool) 66 + .await?; 67 + 68 + // Only insert if the exact combination doesn't exist 69 + if !exists { 70 + sqlx::query( 71 + "INSERT INTO links (original_url, short_code, user_id) 72 + VALUES (?1, ?2, ?3)", 73 + ) 74 + .bind(url) 75 + .bind(code) 76 + .bind(1) 77 + .execute(pool) 78 + .await?; 79 + info!("Created initial link: {} -> {} for user_id: 1", code, url); 80 + } else { 81 + info!("Skipped existing link: {} -> {} for user_id: 1", code, url); 82 + } 83 + } 84 + } 85 + } 86 + } 87 + } 88 + Ok(()) 89 + } 90 + 91 + async fn create_admin_user(pool: &DatabasePool, email: &str, password: &str) -> Result<()> { 92 + use argon2::{ 93 + password_hash::{rand_core::OsRng, SaltString}, 94 + Argon2, PasswordHasher, 95 + }; 96 + 97 + let salt = SaltString::generate(&mut OsRng); 98 + let argon2 = Argon2::default(); 99 + let password_hash = argon2 100 + .hash_password(password.as_bytes(), &salt) 101 + .map_err(|e| anyhow::anyhow!("Password hashing error: {}", e))? 102 + .to_string(); 103 + 104 + match pool { 105 + DatabasePool::Postgres(pool) => { 106 + sqlx::query( 107 + "INSERT INTO users (email, password_hash) 108 + VALUES ($1, $2) 109 + ON CONFLICT (email) DO NOTHING", 110 + ) 111 + .bind(email) 112 + .bind(&password_hash) 113 + .execute(pool) 114 + .await?; 115 + } 116 + DatabasePool::Sqlite(pool) => { 117 + sqlx::query( 118 + "INSERT OR IGNORE INTO users (email, password_hash) 119 + VALUES (?1, ?2)", 120 + ) 121 + .bind(email) 122 + .bind(&password_hash) 123 + .execute(pool) 124 + .await?; 125 + } 126 + } 127 + info!("Created admin user: {}", email); 128 + Ok(()) 129 + } 9 130 10 131 #[actix_web::main] 11 132 async fn main() -> Result<()> { ··· 15 136 // Initialize logging 16 137 tracing_subscriber::fmt::init(); 17 138 18 - // Database connection string from environment 19 - let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set"); 139 + // Create database connection pool 140 + let pool = create_db_pool().await?; 141 + run_migrations(&pool).await?; 142 + 143 + // First check if admin credentials are provided in environment variables 144 + let admin_credentials = match ( 145 + std::env::var("SIMPLELINK_USER"), 146 + std::env::var("SIMPLELINK_PASS"), 147 + ) { 148 + (Ok(user), Ok(pass)) => Some((user, pass)), 149 + _ => None, 150 + }; 151 + 152 + if let Some((email, password)) = admin_credentials { 153 + // Now check for existing users 154 + let user_count = match &pool { 155 + DatabasePool::Postgres(pool) => { 156 + let mut tx = pool.begin().await?; 157 + let count = 158 + sqlx::query_as::<Postgres, (i64,)>("SELECT COUNT(*)::bigint FROM users") 159 + .fetch_one(&mut *tx) 160 + .await? 161 + .0; 162 + tx.commit().await?; 163 + count 164 + } 165 + DatabasePool::Sqlite(pool) => { 166 + let mut tx = pool.begin().await?; 167 + let count = sqlx::query_as::<Sqlite, (i64,)>("SELECT COUNT(*) FROM users") 168 + .fetch_one(&mut *tx) 169 + .await? 170 + .0; 171 + tx.commit().await?; 172 + count 173 + } 174 + }; 20 175 21 - // Create database connection pool 22 - let pool = PgPoolOptions::new() 23 - .max_connections(5) 24 - .acquire_timeout(std::time::Duration::from_secs(3)) 25 - .connect(&database_url) 26 - .await?; 176 + if user_count == 0 { 177 + info!("No users found, creating admin user: {}", email); 178 + match create_admin_user(&pool, &email, &password).await { 179 + Ok(_) => info!("Successfully created admin user"), 180 + Err(e) => { 181 + error!("Failed to create admin user: {}", e); 182 + return Err(anyhow::anyhow!("Failed to create admin user: {}", e)); 183 + } 184 + } 185 + } 186 + } else { 187 + info!( 188 + "No admin credentials provided in environment variables, skipping admin user creation" 189 + ); 190 + } 27 191 28 - // Run database migrations 29 - sqlx::migrate!("./migrations").run(&pool).await?; 192 + // Create initial links from environment variables 193 + create_initial_links(&pool).await?; 30 194 31 195 let admin_token = check_and_generate_admin_token(&pool).await?; 32 196 ··· 63 227 "/links/{id}/sources", 64 228 web::get().to(handlers::get_link_sources), 65 229 ) 230 + .route("/links/{id}", web::patch().to(handlers::edit_link)) 66 231 .route("/auth/register", web::post().to(handlers::register)) 67 232 .route("/auth/login", web::post().to(handlers::login)) 233 + .route( 234 + "/auth/check-first-user", 235 + web::get().to(handlers::check_first_user), 236 + ) 68 237 .route("/health", web::get().to(handlers::health_check)), 69 238 ) 70 239 .service(web::resource("/{short_code}").route(web::get().to(handlers::redirect_to_url))) 71 - .service(fs::Files::new("/", "./static").index_file("index.html")) 240 + .default_service(web::route().to(|req: actix_web::HttpRequest| async move { 241 + let path = req.path().trim_start_matches('/'); 242 + let path = if path.is_empty() { "index.html" } else { path }; 243 + serve_static_file(path).await 244 + })) 72 245 }) 73 246 .workers(2) 74 247 .backlog(10_000)
+77 -5
src/models.rs
··· 1 + use anyhow::Result; 2 + use futures::future::BoxFuture; 3 + use serde::{Deserialize, Serialize}; 4 + use sqlx::postgres::PgRow; 5 + use sqlx::sqlite::SqliteRow; 6 + use sqlx::FromRow; 7 + use sqlx::Pool; 8 + use sqlx::Postgres; 9 + use sqlx::Sqlite; 10 + use sqlx::Transaction; 1 11 use std::time::{SystemTime, UNIX_EPOCH}; 2 12 3 - use chrono::NaiveDate; 4 - use serde::{Deserialize, Serialize}; 5 - use sqlx::FromRow; 13 + #[derive(Clone)] 14 + pub enum DatabasePool { 15 + Postgres(Pool<Postgres>), 16 + Sqlite(Pool<Sqlite>), 17 + } 18 + 19 + impl DatabasePool { 20 + pub async fn begin(&self) -> Result<Box<dyn std::any::Any + Send>> { 21 + match self { 22 + DatabasePool::Postgres(pool) => Ok(Box::new(pool.begin().await?)), 23 + DatabasePool::Sqlite(pool) => Ok(Box::new(pool.begin().await?)), 24 + } 25 + } 26 + 27 + pub async fn fetch_optional<T>(&self, pg_query: &str, sqlite_query: &str) -> Result<Option<T>> 28 + where 29 + T: for<'r> FromRow<'r, PgRow> + for<'r> FromRow<'r, SqliteRow> + Send + Sync + Unpin, 30 + { 31 + match self { 32 + DatabasePool::Postgres(pool) => { 33 + Ok(sqlx::query_as(pg_query).fetch_optional(pool).await?) 34 + } 35 + DatabasePool::Sqlite(pool) => { 36 + Ok(sqlx::query_as(sqlite_query).fetch_optional(pool).await?) 37 + } 38 + } 39 + } 40 + 41 + pub async fn execute(&self, pg_query: &str, sqlite_query: &str) -> Result<()> { 42 + match self { 43 + DatabasePool::Postgres(pool) => { 44 + sqlx::query(pg_query).execute(pool).await?; 45 + Ok(()) 46 + } 47 + DatabasePool::Sqlite(pool) => { 48 + sqlx::query(sqlite_query).execute(pool).await?; 49 + Ok(()) 50 + } 51 + } 52 + } 53 + 54 + pub async fn transaction<'a, F, R>(&'a self, f: F) -> Result<R> 55 + where 56 + F: for<'c> Fn(&'c mut Transaction<'_, Postgres>) -> BoxFuture<'c, Result<R>> 57 + + for<'c> Fn(&'c mut Transaction<'_, Sqlite>) -> BoxFuture<'c, Result<R>> 58 + + Copy, 59 + R: Send + 'static, 60 + { 61 + match self { 62 + DatabasePool::Postgres(pool) => { 63 + let mut tx = pool.begin().await?; 64 + let result = f(&mut tx).await?; 65 + tx.commit().await?; 66 + Ok(result) 67 + } 68 + DatabasePool::Sqlite(pool) => { 69 + let mut tx = pool.begin().await?; 70 + let result = f(&mut tx).await?; 71 + tx.commit().await?; 72 + Ok(result) 73 + } 74 + } 75 + } 76 + } 6 77 7 78 #[derive(Debug, Serialize, Deserialize)] 8 79 pub struct Claims { ··· 16 87 .duration_since(UNIX_EPOCH) 17 88 .unwrap() 18 89 .as_secs() as usize 19 - + 24 * 60 * 60; // 24 hours from now 90 + + 14 * 24 * 60 * 60; // 2 weeks from now 20 91 21 92 Self { sub: user_id, exp } 22 93 } ··· 73 144 74 145 #[derive(sqlx::FromRow, Serialize)] 75 146 pub struct ClickStats { 76 - pub date: NaiveDate, 147 + pub date: String, 77 148 pub clicks: i64, 78 149 } 79 150 80 151 #[derive(sqlx::FromRow, Serialize)] 81 152 pub struct SourceStats { 153 + pub date: String, 82 154 pub source: String, 83 155 pub count: i64, 84 156 }