git.iko.soy/rowtype-yoga/purescript-yoga-http-api
on feat/custom-type-errors help sign in
Add re-export hub, tests, vitest config, and package.json
commita5409fc73d21a55503bfaf3403983cf89be71410 authorMark <mark.eibes@gmail.com> dateFri 6 Feb 2026, 21:16 (8 months ago) parent1437b44
13 files changed+2368−1
bun.lock+891 package.json+17 spago.lock+180−1 spago.yaml+11 src/Yoga/HTTP/API/Route.purs+33 test/MetadataValidationTest.Spec.purs+205 test/OperatorTest.Spec.purs+30 test/OperatorTest.purs+141 test/ParserTest.Spec.purs+111 test/ParserTest.purs+354 test/Test.Operators.purs+37 test/VariantResponseTest.Spec.purs+349 vitest.config.js+9
bun.locknew file+891
@@ -0,0 +1,891 @@
1+{
2+ "lockfileVersion": 1,
3+ "workspaces": {
4+ "": {
5+ "name": "purescript-yoga-http-api",
6+ "devDependencies": {
7+ "jsdom": "^24.0.0",
8+ "purescript": "^0.15.15",
9+ "spago": "^1.0.3",
10+ "vitest": "^1.0.0",
11+ },
12+ },
13+ },
14+ "packages": {
15+ "@asamuzakjp/css-color": ["@asamuzakjp/css-color@3.2.0", "", { "dependencies": { "@csstools/css-calc": "^2.1.3", "@csstools/css-color-parser": "^3.0.9", "@csstools/css-parser-algorithms": "^3.0.4", "@csstools/css-tokenizer": "^3.0.3", "lru-cache": "^10.4.3" } }, "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw=="],
16+
17+ "@csstools/color-helpers": ["@csstools/color-helpers@5.1.0", "", {}, "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA=="],
18+
19+ "@csstools/css-calc": ["@csstools/css-calc@2.1.4", "", { "peerDependencies": { "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4" } }, "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ=="],
20+
21+ "@csstools/css-color-parser": ["@csstools/css-color-parser@3.1.0", "", { "dependencies": { "@csstools/color-helpers": "^5.1.0", "@csstools/css-calc": "^2.1.4" }, "peerDependencies": { "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4" } }, "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA=="],
22+
23+ "@csstools/css-parser-algorithms": ["@csstools/css-parser-algorithms@3.0.5", "", { "peerDependencies": { "@csstools/css-tokenizer": "^3.0.4" } }, "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ=="],
24+
25+ "@csstools/css-tokenizer": ["@csstools/css-tokenizer@3.0.4", "", {}, "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw=="],
26+
27+ "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
28+
29+ "@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="],
30+
31+ "@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="],
32+
33+ "@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="],
34+
35+ "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="],
36+
37+ "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="],
38+
39+ "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="],
40+
41+ "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="],
42+
43+ "@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="],
44+
45+ "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="],
46+
47+ "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="],
48+
49+ "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="],
50+
51+ "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="],
52+
53+ "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="],
54+
55+ "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="],
56+
57+ "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="],
58+
59+ "@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="],
60+
61+ "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="],
62+
63+ "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="],
64+
65+ "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="],
66+
67+ "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="],
68+
69+ "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="],
70+
71+ "@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="],
72+
73+ "@gar/promisify": ["@gar/promisify@1.1.3", "", {}, "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw=="],
74+
75+ "@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="],
76+
77+ "@isaacs/brace-expansion": ["@isaacs/brace-expansion@5.0.1", "", { "dependencies": { "@isaacs/balanced-match": "^4.0.1" } }, "sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ=="],
78+
79+ "@isaacs/cliui": ["@isaacs/cliui@9.0.0", "", {}, "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg=="],
80+
81+ "@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],
82+
83+ "@jest/schemas": ["@jest/schemas@29.6.3", "", { "dependencies": { "@sinclair/typebox": "^0.27.8" } }, "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA=="],
84+
85+ "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
86+
87+ "@nodelib/fs.scandir": ["@nodelib/fs.scandir@4.0.1", "", { "dependencies": { "@nodelib/fs.stat": "4.0.0", "run-parallel": "^1.2.0" } }, "sha512-vAkI715yhnmiPupY+dq+xenu5Tdf2TBQ66jLvBIcCddtz+5Q8LbMKaf9CIJJreez8fQ8fgaY+RaywQx8RJIWpw=="],
88+
89+ "@nodelib/fs.stat": ["@nodelib/fs.stat@4.0.0", "", {}, "sha512-ctr6bByzksKRCV0bavi8WoQevU6plSp2IkllIsEqaiKe2mwNNnaluhnRhcsgGZHrrHk57B3lf95MkLMO3STYcg=="],
90+
91+ "@nodelib/fs.walk": ["@nodelib/fs.walk@3.0.1", "", { "dependencies": { "@nodelib/fs.scandir": "4.0.1", "fastq": "^1.15.0" } }, "sha512-nIh/M6Kh3ZtOmlY00DaUYB4xeeV6F3/ts1l29iwl3/cfyY/OuCfUx+v08zgx8TKPTifXRcjjqVQ4KB2zOYSbyw=="],
92+
93+ "@npmcli/fs": ["@npmcli/fs@2.1.2", "", { "dependencies": { "@gar/promisify": "^1.1.3", "semver": "^7.3.5" } }, "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ=="],
94+
95+ "@npmcli/move-file": ["@npmcli/move-file@2.0.1", "", { "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" } }, "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ=="],
96+
97+ "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.57.1", "", { "os": "android", "cpu": "arm" }, "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg=="],
98+
99+ "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.57.1", "", { "os": "android", "cpu": "arm64" }, "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w=="],
100+
101+ "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.57.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg=="],
102+
103+ "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.57.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w=="],
104+
105+ "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.57.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug=="],
106+
107+ "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.57.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q=="],
108+
109+ "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.57.1", "", { "os": "linux", "cpu": "arm" }, "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw=="],
110+
111+ "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.57.1", "", { "os": "linux", "cpu": "arm" }, "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw=="],
112+
113+ "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.57.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g=="],
114+
115+ "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.57.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q=="],
116+
117+ "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.57.1", "", { "os": "linux", "cpu": "none" }, "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA=="],
118+
119+ "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.57.1", "", { "os": "linux", "cpu": "none" }, "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw=="],
120+
121+ "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.57.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w=="],
122+
123+ "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.57.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw=="],
124+
125+ "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.57.1", "", { "os": "linux", "cpu": "none" }, "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A=="],
126+
127+ "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.57.1", "", { "os": "linux", "cpu": "none" }, "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw=="],
128+
129+ "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.57.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg=="],
130+
131+ "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.57.1", "", { "os": "linux", "cpu": "x64" }, "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg=="],
132+
133+ "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.57.1", "", { "os": "linux", "cpu": "x64" }, "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw=="],
134+
135+ "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.57.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw=="],
136+
137+ "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.57.1", "", { "os": "none", "cpu": "arm64" }, "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ=="],
138+
139+ "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.57.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ=="],
140+
141+ "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.57.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew=="],
142+
143+ "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.57.1", "", { "os": "win32", "cpu": "x64" }, "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ=="],
144+
145+ "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.57.1", "", { "os": "win32", "cpu": "x64" }, "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA=="],
146+
147+ "@sinclair/typebox": ["@sinclair/typebox@0.27.10", "", {}, "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA=="],
148+
149+ "@tootallnate/once": ["@tootallnate/once@2.0.0", "", {}, "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A=="],
150+
151+ "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
152+
153+ "@vitest/expect": ["@vitest/expect@1.6.1", "", { "dependencies": { "@vitest/spy": "1.6.1", "@vitest/utils": "1.6.1", "chai": "^4.3.10" } }, "sha512-jXL+9+ZNIJKruofqXuuTClf44eSpcHlgj3CiuNihUF3Ioujtmc0zIa3UJOW5RjDK1YLBJZnWBlPuqhYycLioog=="],
154+
155+ "@vitest/runner": ["@vitest/runner@1.6.1", "", { "dependencies": { "@vitest/utils": "1.6.1", "p-limit": "^5.0.0", "pathe": "^1.1.1" } }, "sha512-3nSnYXkVkf3mXFfE7vVyPmi3Sazhb/2cfZGGs0JRzFsPFvAMBEcrweV1V1GsrstdXeKCTXlJbvnQwGWgEIHmOA=="],
156+
157+ "@vitest/snapshot": ["@vitest/snapshot@1.6.1", "", { "dependencies": { "magic-string": "^0.30.5", "pathe": "^1.1.1", "pretty-format": "^29.7.0" } }, "sha512-WvidQuWAzU2p95u8GAKlRMqMyN1yOJkGHnx3M1PL9Raf7AQ1kwLKg04ADlCa3+OXUZE7BceOhVZiuWAbzCKcUQ=="],
158+
159+ "@vitest/spy": ["@vitest/spy@1.6.1", "", { "dependencies": { "tinyspy": "^2.2.0" } }, "sha512-MGcMmpGkZebsMZhbQKkAf9CX5zGvjkBTqf8Zx3ApYWXr3wG+QvEu2eXWfnIIWYSJExIp4V9FCKDEeygzkYrXMw=="],
160+
161+ "@vitest/utils": ["@vitest/utils@1.6.1", "", { "dependencies": { "diff-sequences": "^29.6.3", "estree-walker": "^3.0.3", "loupe": "^2.3.7", "pretty-format": "^29.7.0" } }, "sha512-jOrrUvXM4Av9ZWiG1EajNto0u96kWAhJ1LmPmJhXXQx/32MecEKd10pOLYgS2BQx1TgkGhloPU1ArDW2vvaY6g=="],
162+
163+ "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
164+
165+ "acorn-walk": ["acorn-walk@8.3.4", "", { "dependencies": { "acorn": "^8.11.0" } }, "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g=="],
166+
167+ "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
168+
169+ "agentkeepalive": ["agentkeepalive@4.6.0", "", { "dependencies": { "humanize-ms": "^1.2.1" } }, "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ=="],
170+
171+ "aggregate-error": ["aggregate-error@3.1.0", "", { "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" } }, "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA=="],
172+
173+ "ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="],
174+
175+ "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
176+
177+ "ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
178+
179+ "aproba": ["aproba@1.2.0", "", {}, "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="],
180+
181+ "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
182+
183+ "asn1": ["asn1@0.2.6", "", { "dependencies": { "safer-buffer": "~2.1.0" } }, "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ=="],
184+
185+ "assertion-error": ["assertion-error@1.1.0", "", {}, "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw=="],
186+
187+ "astral-regex": ["astral-regex@2.0.0", "", {}, "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ=="],
188+
189+ "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
190+
191+ "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
192+
193+ "bcrypt-pbkdf": ["bcrypt-pbkdf@1.0.2", "", { "dependencies": { "tweetnacl": "^0.14.3" } }, "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w=="],
194+
195+ "bluebird": ["bluebird@3.7.2", "", {}, "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="],
196+
197+ "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
198+
199+ "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
200+
201+ "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
202+
203+ "buildcheck": ["buildcheck@0.0.7", "", {}, "sha512-lHblz4ahamxpTmnsk+MNTRWsjYKv965MwOrSJyeD588rR3Jcu7swE+0wN5F+PbL5cjgu/9ObkhfzEPuofEMwLA=="],
204+
205+ "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],
206+
207+ "byline": ["byline@5.0.0", "", {}, "sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q=="],
208+
209+ "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="],
210+
211+ "cacache": ["cacache@11.3.3", "", { "dependencies": { "bluebird": "^3.5.5", "chownr": "^1.1.1", "figgy-pudding": "^3.5.1", "glob": "^7.1.4", "graceful-fs": "^4.1.15", "lru-cache": "^5.1.1", "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "move-concurrently": "^1.0.1", "promise-inflight": "^1.0.1", "rimraf": "^2.6.3", "ssri": "^6.0.1", "unique-filename": "^1.1.1", "y18n": "^4.0.0" } }, "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA=="],
212+
213+ "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
214+
215+ "chai": ["chai@4.5.0", "", { "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.3", "deep-eql": "^4.1.3", "get-func-name": "^2.0.2", "loupe": "^2.3.6", "pathval": "^1.1.1", "type-detect": "^4.1.0" } }, "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw=="],
216+
217+ "chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
218+
219+ "check-error": ["check-error@1.0.3", "", { "dependencies": { "get-func-name": "^2.0.2" } }, "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg=="],
220+
221+ "chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
222+
223+ "clean-stack": ["clean-stack@2.2.0", "", {}, "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A=="],
224+
225+ "cli-cursor": ["cli-cursor@3.1.0", "", { "dependencies": { "restore-cursor": "^3.1.0" } }, "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="],
226+
227+ "color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
228+
229+ "color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
230+
231+ "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
232+
233+ "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
234+
235+ "concat-stream": ["concat-stream@1.6.2", "", { "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" } }, "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw=="],
236+
237+ "confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="],
238+
239+ "copy-concurrently": ["copy-concurrently@1.0.5", "", { "dependencies": { "aproba": "^1.1.1", "fs-write-stream-atomic": "^1.0.8", "iferr": "^0.1.5", "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.0" } }, "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A=="],
240+
241+ "core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="],
242+
243+ "cpu-features": ["cpu-features@0.0.10", "", { "dependencies": { "buildcheck": "~0.0.6", "nan": "^2.19.0" } }, "sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA=="],
244+
245+ "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
246+
247+ "cssstyle": ["cssstyle@4.6.0", "", { "dependencies": { "@asamuzakjp/css-color": "^3.2.0", "rrweb-cssom": "^0.8.0" } }, "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg=="],
248+
249+ "cyclist": ["cyclist@1.0.2", "", {}, "sha512-0sVXIohTfLqVIW3kb/0n6IiWF3Ifj5nm2XaSrLq2DI6fKIGa2fYAZdk917rUneaeLVpYfFcyXE2ft0fe3remsA=="],
250+
251+ "data-urls": ["data-urls@5.0.0", "", { "dependencies": { "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0" } }, "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg=="],
252+
253+ "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
254+
255+ "decimal.js": ["decimal.js@10.6.0", "", {}, "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg=="],
256+
257+ "deep-eql": ["deep-eql@4.1.4", "", { "dependencies": { "type-detect": "^4.0.0" } }, "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg=="],
258+
259+ "default-browser": ["default-browser@5.5.0", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw=="],
260+
261+ "default-browser-id": ["default-browser-id@5.0.1", "", {}, "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q=="],
262+
263+ "define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="],
264+
265+ "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
266+
267+ "diff-sequences": ["diff-sequences@29.6.3", "", {}, "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q=="],
268+
269+ "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
270+
271+ "duplexify": ["duplexify@3.7.1", "", { "dependencies": { "end-of-stream": "^1.0.0", "inherits": "^2.0.1", "readable-stream": "^2.0.0", "stream-shift": "^1.0.0" } }, "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g=="],
272+
273+ "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
274+
275+ "encoding": ["encoding@0.1.13", "", { "dependencies": { "iconv-lite": "^0.6.2" } }, "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A=="],
276+
277+ "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
278+
279+ "entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
280+
281+ "env-paths": ["env-paths@3.0.0", "", {}, "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A=="],
282+
283+ "err-code": ["err-code@2.0.3", "", {}, "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA=="],
284+
285+ "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
286+
287+ "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
288+
289+ "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
290+
291+ "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
292+
293+ "esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="],
294+
295+ "escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
296+
297+ "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
298+
299+ "execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="],
300+
301+ "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="],
302+
303+ "figgy-pudding": ["figgy-pudding@3.5.2", "", {}, "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw=="],
304+
305+ "filesize": ["filesize@4.2.1", "", {}, "sha512-bP82Hi8VRZX/TUBKfE24iiUGsB/sfm2WUrwTQyAzQrhO3V9IhcBBNBXMyzLY5orACxRyYJ3d2HeRVX+eFv4lmA=="],
306+
307+ "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
308+
309+ "flush-write-stream": ["flush-write-stream@1.1.1", "", { "dependencies": { "inherits": "^2.0.3", "readable-stream": "^2.3.6" } }, "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w=="],
310+
311+ "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],
312+
313+ "form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="],
314+
315+ "from2": ["from2@2.3.0", "", { "dependencies": { "inherits": "^2.0.1", "readable-stream": "^2.0.0" } }, "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g=="],
316+
317+ "fs-extra": ["fs-extra@11.3.3", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg=="],
318+
319+ "fs-minipass": ["fs-minipass@2.1.0", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg=="],
320+
321+ "fs-write-stream-atomic": ["fs-write-stream-atomic@1.0.10", "", { "dependencies": { "graceful-fs": "^4.1.2", "iferr": "^0.1.5", "imurmurhash": "^0.1.4", "readable-stream": "1 || 2" } }, "sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA=="],
322+
323+ "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="],
324+
325+ "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
326+
327+ "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
328+
329+ "fuse.js": ["fuse.js@7.1.0", "", {}, "sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ=="],
330+
331+ "get-func-name": ["get-func-name@2.0.2", "", {}, "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ=="],
332+
333+ "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
334+
335+ "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
336+
337+ "get-stream": ["get-stream@8.0.1", "", {}, "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA=="],
338+
339+ "glob": ["glob@11.1.0", "", { "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw=="],
340+
341+ "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
342+
343+ "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
344+
345+ "has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
346+
347+ "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
348+
349+ "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
350+
351+ "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
352+
353+ "html-encoding-sniffer": ["html-encoding-sniffer@4.0.0", "", { "dependencies": { "whatwg-encoding": "^3.1.1" } }, "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ=="],
354+
355+ "http-cache-semantics": ["http-cache-semantics@4.2.0", "", {}, "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="],
356+
357+ "http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="],
358+
359+ "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
360+
361+ "human-signals": ["human-signals@5.0.0", "", {}, "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ=="],
362+
363+ "humanize-ms": ["humanize-ms@1.2.1", "", { "dependencies": { "ms": "^2.0.0" } }, "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ=="],
364+
365+ "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
366+
367+ "iferr": ["iferr@0.1.5", "", {}, "sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA=="],
368+
369+ "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
370+
371+ "indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="],
372+
373+ "infer-owner": ["infer-owner@1.0.4", "", {}, "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A=="],
374+
375+ "inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="],
376+
377+ "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
378+
379+ "ip-address": ["ip-address@10.1.0", "", {}, "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q=="],
380+
381+ "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="],
382+
383+ "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
384+
385+ "is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="],
386+
387+ "is-lambda": ["is-lambda@1.0.1", "", {}, "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ=="],
388+
389+ "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
390+
391+ "is-plain-obj": ["is-plain-obj@2.1.0", "", {}, "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA=="],
392+
393+ "is-potential-custom-element-name": ["is-potential-custom-element-name@1.0.1", "", {}, "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ=="],
394+
395+ "is-stream": ["is-stream@3.0.0", "", {}, "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA=="],
396+
397+ "is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="],
398+
399+ "isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="],
400+
401+ "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
402+
403+ "jackspeak": ["jackspeak@4.2.1", "", { "dependencies": { "@isaacs/cliui": "^9.0.0" } }, "sha512-GPBXyfcZSGujjddPeA+V34bW70ZJT7jzCEbloVasSH4yjiqWqXHX8iZQtZdVbOhc5esSeAIuiSmMutRZQB/olg=="],
404+
405+ "js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="],
406+
407+ "jsdom": ["jsdom@24.1.3", "", { "dependencies": { "cssstyle": "^4.0.1", "data-urls": "^5.0.0", "decimal.js": "^10.4.3", "form-data": "^4.0.0", "html-encoding-sniffer": "^4.0.0", "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.5", "is-potential-custom-element-name": "^1.0.1", "nwsapi": "^2.2.12", "parse5": "^7.1.2", "rrweb-cssom": "^0.7.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", "tough-cookie": "^4.1.4", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0", "ws": "^8.18.0", "xml-name-validator": "^5.0.0" }, "peerDependencies": { "canvas": "^2.11.2" }, "optionalPeers": ["canvas"] }, "sha512-MyL55p3Ut3cXbeBEG7Hcv0mVM8pp8PBNWxRqchZnSfAiES1v1mRnMeFfaHWIPULpwsYfvO+ZmMZz5tGCnjzDUQ=="],
408+
409+ "jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="],
410+
411+ "linkify-it": ["linkify-it@5.0.0", "", { "dependencies": { "uc.micro": "^2.0.0" } }, "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ=="],
412+
413+ "local-pkg": ["local-pkg@0.5.1", "", { "dependencies": { "mlly": "^1.7.3", "pkg-types": "^1.2.1" } }, "sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ=="],
414+
415+ "log-symbols": ["log-symbols@3.0.0", "", { "dependencies": { "chalk": "^2.4.2" } }, "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ=="],
416+
417+ "log-update": ["log-update@4.0.0", "", { "dependencies": { "ansi-escapes": "^4.3.0", "cli-cursor": "^3.1.0", "slice-ansi": "^4.0.0", "wrap-ansi": "^6.2.0" } }, "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg=="],
418+
419+ "loupe": ["loupe@2.3.7", "", { "dependencies": { "get-func-name": "^2.0.1" } }, "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA=="],
420+
421+ "lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
422+
423+ "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
424+
425+ "make-fetch-happen": ["make-fetch-happen@10.2.1", "", { "dependencies": { "agentkeepalive": "^4.2.1", "cacache": "^16.1.0", "http-cache-semantics": "^4.1.0", "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "is-lambda": "^1.0.1", "lru-cache": "^7.7.1", "minipass": "^3.1.6", "minipass-collect": "^1.0.2", "minipass-fetch": "^2.0.3", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", "promise-retry": "^2.0.1", "socks-proxy-agent": "^7.0.0", "ssri": "^9.0.0" } }, "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w=="],
426+
427+ "markdown-it": ["markdown-it@14.1.0", "", { "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", "linkify-it": "^5.0.0", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" }, "bin": { "markdown-it": "bin/markdown-it.mjs" } }, "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg=="],
428+
429+ "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
430+
431+ "mdurl": ["mdurl@2.0.0", "", {}, "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w=="],
432+
433+ "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="],
434+
435+ "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
436+
437+ "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
438+
439+ "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
440+
441+ "mimic-fn": ["mimic-fn@4.0.0", "", {}, "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="],
442+
443+ "minimatch": ["minimatch@10.1.2", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.1" } }, "sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw=="],
444+
445+ "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
446+
447+ "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
448+
449+ "minipass-collect": ["minipass-collect@1.0.2", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA=="],
450+
451+ "minipass-fetch": ["minipass-fetch@2.1.2", "", { "dependencies": { "minipass": "^3.1.6", "minipass-sized": "^1.0.3", "minizlib": "^2.1.2" }, "optionalDependencies": { "encoding": "^0.1.13" } }, "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA=="],
452+
453+ "minipass-flush": ["minipass-flush@1.0.5", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw=="],
454+
455+ "minipass-pipeline": ["minipass-pipeline@1.2.4", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A=="],
456+
457+ "minipass-sized": ["minipass-sized@1.0.3", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g=="],
458+
459+ "minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="],
460+
461+ "mississippi": ["mississippi@3.0.0", "", { "dependencies": { "concat-stream": "^1.5.0", "duplexify": "^3.4.2", "end-of-stream": "^1.1.0", "flush-write-stream": "^1.0.0", "from2": "^2.1.0", "parallel-transform": "^1.1.0", "pump": "^3.0.0", "pumpify": "^1.3.3", "stream-each": "^1.1.0", "through2": "^2.0.0" } }, "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA=="],
462+
463+ "mkdirp": ["mkdirp@0.5.6", "", { "dependencies": { "minimist": "^1.2.6" }, "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="],
464+
465+ "mlly": ["mlly@1.8.0", "", { "dependencies": { "acorn": "^8.15.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.1" } }, "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g=="],
466+
467+ "move-concurrently": ["move-concurrently@1.0.1", "", { "dependencies": { "aproba": "^1.1.1", "copy-concurrently": "^1.0.0", "fs-write-stream-atomic": "^1.0.8", "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.3" } }, "sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ=="],
468+
469+ "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
470+
471+ "nan": ["nan@2.25.0", "", {}, "sha512-0M90Ag7Xn5KMLLZ7zliPWP3rT90P6PN+IzVFS0VqmnPktBk3700xUVv8Ikm9EUaUE5SDWdp/BIxdENzVznpm1g=="],
472+
473+ "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
474+
475+ "negotiator": ["negotiator@0.6.4", "", {}, "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w=="],
476+
477+ "npm-run-path": ["npm-run-path@5.3.0", "", { "dependencies": { "path-key": "^4.0.0" } }, "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ=="],
478+
479+ "nwsapi": ["nwsapi@2.2.23", "", {}, "sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ=="],
480+
481+ "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
482+
483+ "onetime": ["onetime@6.0.0", "", { "dependencies": { "mimic-fn": "^4.0.0" } }, "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ=="],
484+
485+ "open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="],
486+
487+ "p-finally": ["p-finally@2.0.1", "", {}, "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw=="],
488+
489+ "p-limit": ["p-limit@5.0.0", "", { "dependencies": { "yocto-queue": "^1.0.0" } }, "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ=="],
490+
491+ "p-map": ["p-map@4.0.0", "", { "dependencies": { "aggregate-error": "^3.0.0" } }, "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ=="],
492+
493+ "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="],
494+
495+ "parallel-transform": ["parallel-transform@1.2.0", "", { "dependencies": { "cyclist": "^1.0.1", "inherits": "^2.0.3", "readable-stream": "^2.1.5" } }, "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg=="],
496+
497+ "parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="],
498+
499+ "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="],
500+
501+ "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
502+
503+ "path-scurry": ["path-scurry@2.0.1", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA=="],
504+
505+ "pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="],
506+
507+ "pathval": ["pathval@1.1.1", "", {}, "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ=="],
508+
509+ "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
510+
511+ "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
512+
513+ "pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
514+
515+ "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
516+
517+ "pretty-format": ["pretty-format@29.7.0", "", { "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" } }, "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ=="],
518+
519+ "process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="],
520+
521+ "promise-inflight": ["promise-inflight@1.0.1", "", {}, "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g=="],
522+
523+ "promise-retry": ["promise-retry@2.0.1", "", { "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" } }, "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g=="],
524+
525+ "psl": ["psl@1.15.0", "", { "dependencies": { "punycode": "^2.3.1" } }, "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w=="],
526+
527+ "pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="],
528+
529+ "pumpify": ["pumpify@1.5.1", "", { "dependencies": { "duplexify": "^3.6.0", "inherits": "^2.0.3", "pump": "^2.0.0" } }, "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ=="],
530+
531+ "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
532+
533+ "punycode.js": ["punycode.js@2.3.1", "", {}, "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA=="],
534+
535+ "purescript": ["purescript@0.15.15", "", { "dependencies": { "purescript-installer": "^0.3.5" }, "bin": { "purs": "purs.bin" } }, "sha512-4gwLNJa4KRiV+Wl+lyMY4MUFM6cSnIqvz7MvSTdLdvXJN2P9CrABnNbSspaokkNRFd9soWHBFDlYsAtRchqHtg=="],
536+
537+ "purescript-installer": ["purescript-installer@0.3.5", "", { "dependencies": { "byline": "^5.0.0", "cacache": "^11.3.2", "chalk": "^2.4.2", "env-paths": "^2.2.0", "execa": "^2.0.3", "filesize": "^4.1.2", "is-plain-obj": "^2.0.0", "log-symbols": "^3.0.0", "log-update": "^4.0.0", "make-fetch-happen": "^10.0.0", "minimist": "^1.2.0", "ms": "^2.1.2", "once": "^1.4.0", "rimraf": "^2.6.3", "semver": "^7.3.7", "tar": "^6.1.11", "which": "^1.3.1", "zen-observable": "^0.8.14" }, "bin": { "install-purescript": "index.js" } }, "sha512-w04BBvW4BSQlspLsZ9Bs5vtUBZqvC4bC+FizC5GUp2/rpmYvXJ0CTf79Q3MKo2A8p1ZjqbhCI+SqdTQ30UZUIQ=="],
538+
539+ "querystringify": ["querystringify@2.2.0", "", {}, "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="],
540+
541+ "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
542+
543+ "react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
544+
545+ "readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
546+
547+ "readline-sync": ["readline-sync@1.4.10", "", {}, "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw=="],
548+
549+ "requires-port": ["requires-port@1.0.0", "", {}, "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="],
550+
551+ "restore-cursor": ["restore-cursor@3.1.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA=="],
552+
553+ "retry": ["retry@0.12.0", "", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="],
554+
555+ "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
556+
557+ "rimraf": ["rimraf@2.7.1", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "./bin.js" } }, "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w=="],
558+
559+ "rollup": ["rollup@4.57.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.57.1", "@rollup/rollup-android-arm64": "4.57.1", "@rollup/rollup-darwin-arm64": "4.57.1", "@rollup/rollup-darwin-x64": "4.57.1", "@rollup/rollup-freebsd-arm64": "4.57.1", "@rollup/rollup-freebsd-x64": "4.57.1", "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", "@rollup/rollup-linux-arm-musleabihf": "4.57.1", "@rollup/rollup-linux-arm64-gnu": "4.57.1", "@rollup/rollup-linux-arm64-musl": "4.57.1", "@rollup/rollup-linux-loong64-gnu": "4.57.1", "@rollup/rollup-linux-loong64-musl": "4.57.1", "@rollup/rollup-linux-ppc64-gnu": "4.57.1", "@rollup/rollup-linux-ppc64-musl": "4.57.1", "@rollup/rollup-linux-riscv64-gnu": "4.57.1", "@rollup/rollup-linux-riscv64-musl": "4.57.1", "@rollup/rollup-linux-s390x-gnu": "4.57.1", "@rollup/rollup-linux-x64-gnu": "4.57.1", "@rollup/rollup-linux-x64-musl": "4.57.1", "@rollup/rollup-openbsd-x64": "4.57.1", "@rollup/rollup-openharmony-arm64": "4.57.1", "@rollup/rollup-win32-arm64-msvc": "4.57.1", "@rollup/rollup-win32-ia32-msvc": "4.57.1", "@rollup/rollup-win32-x64-gnu": "4.57.1", "@rollup/rollup-win32-x64-msvc": "4.57.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A=="],
560+
561+ "rrweb-cssom": ["rrweb-cssom@0.7.1", "", {}, "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg=="],
562+
563+ "run-applescript": ["run-applescript@7.1.0", "", {}, "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q=="],
564+
565+ "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
566+
567+ "run-queue": ["run-queue@1.0.3", "", { "dependencies": { "aproba": "^1.1.1" } }, "sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg=="],
568+
569+ "safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
570+
571+ "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
572+
573+ "saxes": ["saxes@6.0.0", "", { "dependencies": { "xmlchars": "^2.2.0" } }, "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA=="],
574+
575+ "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
576+
577+ "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
578+
579+ "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
580+
581+ "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="],
582+
583+ "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
584+
585+ "slice-ansi": ["slice-ansi@4.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" } }, "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ=="],
586+
587+ "smart-buffer": ["smart-buffer@4.2.0", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="],
588+
589+ "socks": ["socks@2.8.7", "", { "dependencies": { "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" } }, "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A=="],
590+
591+ "socks-proxy-agent": ["socks-proxy-agent@7.0.0", "", { "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.3", "socks": "^2.6.2" } }, "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww=="],
592+
593+ "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
594+
595+ "spago": ["spago@1.0.3", "", { "dependencies": { "@nodelib/fs.walk": "^3.0.1", "env-paths": "^3.0.0", "fs-extra": "^11.3.0", "fuse.js": "^7.1.0", "glob": "^11.0.1", "markdown-it": "^14.1.0", "micromatch": "^4.0.8", "open": "^10.1.0", "picomatch": "^4.0.2", "punycode": "^2.3.1", "readline-sync": "^1.4.10", "semver": "^7.7.1", "spdx-expression-parse": "^4.0.0", "ssh2": "^1.16.0", "supports-color": "^10.0.0", "tar": "^7.4.3", "tmp": "^0.2.3", "xhr2": "^0.2.1", "yaml": "^2.7.0" }, "bin": { "spago": "bin/bundle.js" } }, "sha512-3JR6ExwLwaKIMYdc77e6fKqiBKXNentyVkcfhaQx4tGDnWjfHS2Td+zxJZ/28QaBx8s6RXfgFD1VjbALGtM89g=="],
596+
597+ "spdx-exceptions": ["spdx-exceptions@2.5.0", "", {}, "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="],
598+
599+ "spdx-expression-parse": ["spdx-expression-parse@4.0.0", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ=="],
600+
601+ "spdx-license-ids": ["spdx-license-ids@3.0.22", "", {}, "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ=="],
602+
603+ "ssh2": ["ssh2@1.17.0", "", { "dependencies": { "asn1": "^0.2.6", "bcrypt-pbkdf": "^1.0.2" }, "optionalDependencies": { "cpu-features": "~0.0.10", "nan": "^2.23.0" } }, "sha512-wPldCk3asibAjQ/kziWQQt1Wh3PgDFpC0XpwclzKcdT1vql6KeYxf5LIt4nlFkUeR8WuphYMKqUA56X4rjbfgQ=="],
604+
605+ "ssri": ["ssri@6.0.2", "", { "dependencies": { "figgy-pudding": "^3.5.1" } }, "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q=="],
606+
607+ "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="],
608+
609+ "std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="],
610+
611+ "stream-each": ["stream-each@1.2.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "stream-shift": "^1.0.0" } }, "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw=="],
612+
613+ "stream-shift": ["stream-shift@1.0.3", "", {}, "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ=="],
614+
615+ "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
616+
617+ "string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
618+
619+ "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
620+
621+ "strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="],
622+
623+ "strip-literal": ["strip-literal@2.1.1", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q=="],
624+
625+ "supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="],
626+
627+ "symbol-tree": ["symbol-tree@3.2.4", "", {}, "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="],
628+
629+ "tar": ["tar@7.5.7", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ=="],
630+
631+ "through2": ["through2@2.0.5", "", { "dependencies": { "readable-stream": "~2.3.6", "xtend": "~4.0.1" } }, "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ=="],
632+
633+ "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="],
634+
635+ "tinypool": ["tinypool@0.8.4", "", {}, "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ=="],
636+
637+ "tinyspy": ["tinyspy@2.2.1", "", {}, "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A=="],
638+
639+ "tmp": ["tmp@0.2.5", "", {}, "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow=="],
640+
641+ "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
642+
643+ "tough-cookie": ["tough-cookie@4.1.4", "", { "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", "universalify": "^0.2.0", "url-parse": "^1.5.3" } }, "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag=="],
644+
645+ "tr46": ["tr46@5.1.1", "", { "dependencies": { "punycode": "^2.3.1" } }, "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw=="],
646+
647+ "tweetnacl": ["tweetnacl@0.14.5", "", {}, "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA=="],
648+
649+ "type-detect": ["type-detect@4.1.0", "", {}, "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw=="],
650+
651+ "type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="],
652+
653+ "typedarray": ["typedarray@0.0.6", "", {}, "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="],
654+
655+ "uc.micro": ["uc.micro@2.1.0", "", {}, "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="],
656+
657+ "ufo": ["ufo@1.6.3", "", {}, "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q=="],
658+
659+ "unique-filename": ["unique-filename@1.1.1", "", { "dependencies": { "unique-slug": "^2.0.0" } }, "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ=="],
660+
661+ "unique-slug": ["unique-slug@2.0.2", "", { "dependencies": { "imurmurhash": "^0.1.4" } }, "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w=="],
662+
663+ "universalify": ["universalify@0.2.0", "", {}, "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg=="],
664+
665+ "url-parse": ["url-parse@1.5.10", "", { "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" } }, "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ=="],
666+
667+ "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
668+
669+ "vite": ["vite@5.4.21", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw=="],
670+
671+ "vite-node": ["vite-node@1.6.1", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.3.4", "pathe": "^1.1.1", "picocolors": "^1.0.0", "vite": "^5.0.0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-YAXkfvGtuTzwWbDSACdJSg4A4DZiAqckWe90Zapc/sEX3XvHcw1NdurM/6od8J207tSDqNbSsgdCacBgvJKFuA=="],
672+
673+ "vitest": ["vitest@1.6.1", "", { "dependencies": { "@vitest/expect": "1.6.1", "@vitest/runner": "1.6.1", "@vitest/snapshot": "1.6.1", "@vitest/spy": "1.6.1", "@vitest/utils": "1.6.1", "acorn-walk": "^8.3.2", "chai": "^4.3.10", "debug": "^4.3.4", "execa": "^8.0.1", "local-pkg": "^0.5.0", "magic-string": "^0.30.5", "pathe": "^1.1.1", "picocolors": "^1.0.0", "std-env": "^3.5.0", "strip-literal": "^2.0.0", "tinybench": "^2.5.1", "tinypool": "^0.8.3", "vite": "^5.0.0", "vite-node": "1.6.1", "why-is-node-running": "^2.2.2" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", "@vitest/browser": "1.6.1", "@vitest/ui": "1.6.1", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-Ljb1cnSJSivGN0LqXd/zmDbWEM0RNNg2t1QW/XUhYl/qPqyu7CsqeWtqQXHVaJsecLPuDoak2oJcZN2QoRIOag=="],
674+
675+ "w3c-xmlserializer": ["w3c-xmlserializer@5.0.0", "", { "dependencies": { "xml-name-validator": "^5.0.0" } }, "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA=="],
676+
677+ "webidl-conversions": ["webidl-conversions@7.0.0", "", {}, "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g=="],
678+
679+ "whatwg-encoding": ["whatwg-encoding@3.1.1", "", { "dependencies": { "iconv-lite": "0.6.3" } }, "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ=="],
680+
681+ "whatwg-mimetype": ["whatwg-mimetype@4.0.0", "", {}, "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg=="],
682+
683+ "whatwg-url": ["whatwg-url@14.2.0", "", { "dependencies": { "tr46": "^5.1.0", "webidl-conversions": "^7.0.0" } }, "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw=="],
684+
685+ "which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "./bin/which" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="],
686+
687+ "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="],
688+
689+ "wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="],
690+
691+ "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
692+
693+ "ws": ["ws@8.19.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg=="],
694+
695+ "wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="],
696+
697+ "xhr2": ["xhr2@0.2.1", "", {}, "sha512-sID0rrVCqkVNUn8t6xuv9+6FViXjUVXq8H5rWOH2rz9fDNQEd4g0EA2XlcEdJXRz5BMEn4O1pJFdT+z4YHhoWw=="],
698+
699+ "xml-name-validator": ["xml-name-validator@5.0.0", "", {}, "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg=="],
700+
701+ "xmlchars": ["xmlchars@2.2.0", "", {}, "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="],
702+
703+ "xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="],
704+
705+ "y18n": ["y18n@4.0.3", "", {}, "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="],
706+
707+ "yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
708+
709+ "yaml": ["yaml@2.8.2", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A=="],
710+
711+ "yocto-queue": ["yocto-queue@1.2.2", "", {}, "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ=="],
712+
713+ "zen-observable": ["zen-observable@0.8.15", "", {}, "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ=="],
714+
715+ "@npmcli/move-file/mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="],
716+
717+ "@npmcli/move-file/rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="],
718+
719+ "cacache/chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="],
720+
721+ "cacache/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
722+
723+ "cacache/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
724+
725+ "chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
726+
727+ "cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
728+
729+ "cssstyle/rrweb-cssom": ["rrweb-cssom@0.8.0", "", {}, "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw=="],
730+
731+ "fs-extra/universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="],
732+
733+ "fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
734+
735+ "jsonfile/universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="],
736+
737+ "make-fetch-happen/cacache": ["cacache@16.1.3", "", { "dependencies": { "@npmcli/fs": "^2.1.0", "@npmcli/move-file": "^2.0.0", "chownr": "^2.0.0", "fs-minipass": "^2.1.0", "glob": "^8.0.1", "infer-owner": "^1.0.4", "lru-cache": "^7.7.1", "minipass": "^3.1.6", "minipass-collect": "^1.0.2", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "mkdirp": "^1.0.4", "p-map": "^4.0.0", "promise-inflight": "^1.0.1", "rimraf": "^3.0.2", "ssri": "^9.0.0", "tar": "^6.1.11", "unique-filename": "^2.0.0" } }, "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ=="],
738+
739+ "make-fetch-happen/http-proxy-agent": ["http-proxy-agent@5.0.0", "", { "dependencies": { "@tootallnate/once": "2", "agent-base": "6", "debug": "4" } }, "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w=="],
740+
741+ "make-fetch-happen/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="],
742+
743+ "make-fetch-happen/lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="],
744+
745+ "make-fetch-happen/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
746+
747+ "make-fetch-happen/ssri": ["ssri@9.0.1", "", { "dependencies": { "minipass": "^3.1.1" } }, "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q=="],
748+
749+ "markdown-it/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
750+
751+ "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
752+
753+ "minipass-collect/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
754+
755+ "minipass-fetch/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
756+
757+ "minipass-fetch/minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="],
758+
759+ "minipass-flush/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
760+
761+ "minipass-pipeline/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
762+
763+ "minipass-sized/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
764+
765+ "mlly/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
766+
767+ "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
768+
769+ "path-scurry/lru-cache": ["lru-cache@11.2.5", "", {}, "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw=="],
770+
771+ "pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
772+
773+ "pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="],
774+
775+ "pumpify/pump": ["pump@2.0.1", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA=="],
776+
777+ "purescript-installer/env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="],
778+
779+ "purescript-installer/execa": ["execa@2.1.0", "", { "dependencies": { "cross-spawn": "^7.0.0", "get-stream": "^5.0.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^3.0.0", "onetime": "^5.1.0", "p-finally": "^2.0.0", "signal-exit": "^3.0.2", "strip-final-newline": "^2.0.0" } }, "sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw=="],
780+
781+ "purescript-installer/tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="],
782+
783+ "restore-cursor/onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
784+
785+ "restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
786+
787+ "rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
788+
789+ "slice-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
790+
791+ "socks-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
792+
793+ "wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
794+
795+ "@npmcli/move-file/rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
796+
797+ "cacache/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
798+
799+ "cacache/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
800+
801+ "fs-minipass/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
802+
803+ "make-fetch-happen/cacache/chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="],
804+
805+ "make-fetch-happen/cacache/glob": ["glob@8.1.0", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^5.0.1", "once": "^1.3.0" } }, "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ=="],
806+
807+ "make-fetch-happen/cacache/mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="],
808+
809+ "make-fetch-happen/cacache/rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="],
810+
811+ "make-fetch-happen/cacache/tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="],
812+
813+ "make-fetch-happen/cacache/unique-filename": ["unique-filename@2.0.1", "", { "dependencies": { "unique-slug": "^3.0.0" } }, "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A=="],
814+
815+ "make-fetch-happen/http-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
816+
817+ "make-fetch-happen/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
818+
819+ "make-fetch-happen/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
820+
821+ "minipass-collect/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
822+
823+ "minipass-fetch/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
824+
825+ "minipass-fetch/minizlib/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
826+
827+ "minipass-flush/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
828+
829+ "minipass-pipeline/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
830+
831+ "minipass-sized/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
832+
833+ "purescript-installer/execa/get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="],
834+
835+ "purescript-installer/execa/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="],
836+
837+ "purescript-installer/execa/npm-run-path": ["npm-run-path@3.1.0", "", { "dependencies": { "path-key": "^3.0.0" } }, "sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg=="],
838+
839+ "purescript-installer/execa/onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
840+
841+ "purescript-installer/execa/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
842+
843+ "purescript-installer/execa/strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="],
844+
845+ "purescript-installer/tar/chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="],
846+
847+ "purescript-installer/tar/minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="],
848+
849+ "purescript-installer/tar/minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="],
850+
851+ "purescript-installer/tar/mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="],
852+
853+ "purescript-installer/tar/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
854+
855+ "restore-cursor/onetime/mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
856+
857+ "rimraf/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
858+
859+ "slice-ansi/ansi-styles/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
860+
861+ "wrap-ansi/ansi-styles/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
862+
863+ "@npmcli/move-file/rimraf/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
864+
865+ "make-fetch-happen/cacache/glob/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="],
866+
867+ "make-fetch-happen/cacache/rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
868+
869+ "make-fetch-happen/cacache/tar/minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="],
870+
871+ "make-fetch-happen/cacache/tar/minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="],
872+
873+ "make-fetch-happen/cacache/tar/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
874+
875+ "make-fetch-happen/cacache/unique-filename/unique-slug": ["unique-slug@3.0.0", "", { "dependencies": { "imurmurhash": "^0.1.4" } }, "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w=="],
876+
877+ "purescript-installer/execa/onetime/mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
878+
879+ "purescript-installer/tar/minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
880+
881+ "slice-ansi/ansi-styles/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
882+
883+ "wrap-ansi/ansi-styles/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
884+
885+ "make-fetch-happen/cacache/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
886+
887+ "make-fetch-happen/cacache/rimraf/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
888+
889+ "make-fetch-happen/cacache/tar/minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
890+ }
891+}
package.jsonnew file+17
@@ -0,0 +1,17 @@
1+{
2+ "name": "purescript-yoga-http-api",
3+ "version": "0.1.0",
4+ "private": true,
5+ "type": "module",
6+ "scripts": {
7+ "build": "spago build",
8+ "test": "bun run build && bun run vitest run",
9+ "test:watch": "bun run vitest"
10+ },
11+ "devDependencies": {
12+ "jsdom": "^24.0.0",
13+ "purescript": "^0.15.15",
14+ "spago": "^1.0.3",
15+ "vitest": "^1.0.0"
16+ }
17+}
spago.lock+180−1
@@ -62,7 +62,26 @@
6262 ]
6363 },
6464 "test": {
65− "dependencies": []
65+ "dependencies": [
66+ {
67+ "arrays": ">=7.0.0 <8.0.0"
68+ },
69+ {
70+ "console": ">=6.0.0 <7.0.0"
71+ },
72+ {
73+ "foreign-object": ">=4.0.0 <5.0.0"
74+ },
75+ {
76+ "integers": ">=6.0.0 <7.0.0"
77+ },
78+ {
79+ "strings": ">=6.0.0 <7.0.0"
80+ },
81+ {
82+ "vitest": ">=1.0.0 <2.0.0"
83+ }
84+ ]
6685 }
6786 }
6887 },
@@ -564,6 +583,9 @@
564583 }
565584 },
566585 "extra_packages": {
586+ "vitest": {
587+ "path": "../purescript-vitest"
588+ },
567589 "yoga-json": {
568590 "path": "../purescript-yoga-json"
569591 }
@@ -638,6 +660,15 @@
638660 "unfoldable"
639661 ]
640662 },
663+ "console": {
664+ "type": "registry",
665+ "version": "6.1.0",
666+ "integrity": "sha256-3T5PPz1mATZmV0C4GzkCkpLlCa5xG7u8ZNgnLrrrI1Q=",
667+ "dependencies": [
668+ "effect",
669+ "prelude"
670+ ]
671+ },
641672 "const": {
642673 "type": "registry",
643674 "version": "6.0.0",
@@ -934,6 +965,37 @@
934965 "prelude"
935966 ]
936967 },
968+ "js-promise": {
969+ "type": "registry",
970+ "version": "1.0.0",
971+ "integrity": "sha256-u+6+ofIwT5XhT2fbMu4dShwkyWGfPRt9642Cnzw/Wvk=",
972+ "dependencies": [
973+ "effect",
974+ "exceptions",
975+ "foldable-traversable",
976+ "functions",
977+ "maybe",
978+ "newtype",
979+ "prelude"
980+ ]
981+ },
982+ "js-promise-aff": {
983+ "type": "registry",
984+ "version": "1.0.0",
985+ "integrity": "sha256-gEKAdNnTWjXS+tTp/AhYl/ezloKfuoQFcBKrdOx2USo=",
986+ "dependencies": [
987+ "aff",
988+ "control",
989+ "effect",
990+ "either",
991+ "exceptions",
992+ "foreign",
993+ "js-promise",
994+ "maybe",
995+ "prelude",
996+ "transformers"
997+ ]
998+ },
937999 "lazy": {
9381000 "type": "registry",
9391001 "version": "6.0.0",
@@ -975,6 +1037,15 @@
9751037 "prelude"
9761038 ]
9771039 },
1040+ "media-types": {
1041+ "type": "registry",
1042+ "version": "6.0.0",
1043+ "integrity": "sha256-3Wyq+vfqJFTmy1k6DGVnXStxtZxgK631wusDPzlFVxg=",
1044+ "dependencies": [
1045+ "newtype",
1046+ "prelude"
1047+ ]
1048+ },
9781049 "newtype": {
9791050 "type": "registry",
9801051 "version": "5.0.0",
@@ -1249,6 +1320,114 @@
12491320 "unsafe-coerce"
12501321 ]
12511322 },
1323+ "vitest": {
1324+ "type": "local",
1325+ "path": "../purescript-vitest",
1326+ "dependencies": [
1327+ "aff",
1328+ "effect",
1329+ "either",
1330+ "exceptions",
1331+ "js-promise",
1332+ "js-promise-aff",
1333+ "maybe",
1334+ "nullable",
1335+ "prelude",
1336+ "transformers",
1337+ "unsafe-coerce",
1338+ "web-dom",
1339+ "web-html"
1340+ ]
1341+ },
1342+ "web-dom": {
1343+ "type": "registry",
1344+ "version": "6.0.0",
1345+ "integrity": "sha256-rVeqkxChkjqisDvOujy9BMEgGqJkwX3t6g21bXfiG5o=",
1346+ "dependencies": [
1347+ "effect",
1348+ "enums",
1349+ "maybe",
1350+ "newtype",
1351+ "nullable",
1352+ "prelude",
1353+ "unsafe-coerce",
1354+ "web-events"
1355+ ]
1356+ },
1357+ "web-events": {
1358+ "type": "registry",
1359+ "version": "4.0.0",
1360+ "integrity": "sha256-wZNeldG0OU+8qGycUJ9e6vxf1/GC4Ep4OlRMhvjs9LA=",
1361+ "dependencies": [
1362+ "datetime",
1363+ "effect",
1364+ "enums",
1365+ "foreign",
1366+ "functions",
1367+ "maybe",
1368+ "newtype",
1369+ "nullable",
1370+ "prelude",
1371+ "unsafe-coerce"
1372+ ]
1373+ },
1374+ "web-file": {
1375+ "type": "registry",
1376+ "version": "4.0.0",
1377+ "integrity": "sha256-txsdkeWBKU/+5v9m5c6kysgJQSDyV1r7MHaeT4STpjQ=",
1378+ "dependencies": [
1379+ "datetime",
1380+ "effect",
1381+ "enums",
1382+ "foreign",
1383+ "integers",
1384+ "maybe",
1385+ "media-types",
1386+ "nullable",
1387+ "numbers",
1388+ "partial",
1389+ "prelude",
1390+ "tuples",
1391+ "unfoldable",
1392+ "unsafe-coerce",
1393+ "web-events"
1394+ ]
1395+ },
1396+ "web-html": {
1397+ "type": "registry",
1398+ "version": "4.1.0",
1399+ "integrity": "sha256-sMwdo5u2DBOFoQzcJLKBp9b4ChU8YSRBjSi9g1Wk42g=",
1400+ "dependencies": [
1401+ "effect",
1402+ "enums",
1403+ "foreign",
1404+ "functions",
1405+ "js-date",
1406+ "maybe",
1407+ "media-types",
1408+ "newtype",
1409+ "nullable",
1410+ "prelude",
1411+ "unsafe-coerce",
1412+ "web-dom",
1413+ "web-events",
1414+ "web-file",
1415+ "web-storage"
1416+ ]
1417+ },
1418+ "web-storage": {
1419+ "type": "registry",
1420+ "version": "5.0.0",
1421+ "integrity": "sha256-YJfos55oeKtBStNfoWfeflSy8j+4IDym5eaZtIY7YM4=",
1422+ "dependencies": [
1423+ "effect",
1424+ "maybe",
1425+ "nullable",
1426+ "prelude",
1427+ "unsafe-coerce",
1428+ "web-events"
1429+ ]
1430+ },
12521431 "yoga-json": {
12531432 "type": "local",
12541433 "path": "../purescript-yoga-json",
spago.yaml+11
@@ -4,6 +4,8 @@ workspace:
44 extraPackages:
55 yoga-json:
66 path: ../purescript-yoga-json
7+ vitest:
8+ path: ../purescript-vitest
79
810package:
911 name: yoga-http-api
@@ -32,3 +34,12 @@ package:
3234 - unsafe-coerce: ">=6.0.0 <7.0.0"
3335 - variant: ">=8.0.0 <9.0.0"
3436 - yoga-json: ">=5.0.0 <6.0.0"
37+ test:
38+ main: Test.Operators
39+ dependencies:
40+ - vitest: ">=1.0.0 <2.0.0"
41+ - console: ">=6.0.0 <7.0.0"
42+ - foreign-object: ">=4.0.0 <5.0.0"
43+ - arrays: ">=7.0.0 <8.0.0"
44+ - strings: ">=6.0.0 <7.0.0"
45+ - integers: ">=6.0.0 <7.0.0"
src/Yoga/HTTP/API/Route.pursnew file+33
@@ -0,0 +1,33 @@
1+module Yoga.HTTP.API.Route
2+ ( module Yoga.HTTP.API.Path
3+ , module Yoga.HTTP.API.Route.Method
4+ , module Yoga.HTTP.API.Route.Encoding
5+ , module Yoga.HTTP.API.Route.StatusCode
6+ , module Yoga.HTTP.API.Route.HeaderError
7+ , module Yoga.HTTP.API.Route.HeaderValue
8+ , module Yoga.HTTP.API.Route.BearerToken
9+ , module Yoga.HTTP.API.Route.Response
10+ , module Yoga.HTTP.API.Route.Handler
11+ , module Yoga.HTTP.API.Route.RenderMethod
12+ , module Yoga.HTTP.API.Route.OpenAPI
13+ , module Yoga.HTTP.API.Route.OpenAPIMetadata
14+ , module Yoga.HTTP.API.Route.Route
15+ , module Yoga.HTTP.API.Route.RouteHandler
16+ , module Data.Variant
17+ ) where
18+
19+import Data.Variant (Variant)
20+import Yoga.HTTP.API.Path (Path, Root, Lit, Capture, PathCons, Param, QueryParams, Required, type (/), type (:), type (:?), class PathPattern, pathPattern, class ParseParam, parseParam, class ParsePath, parsePath)
21+import Yoga.HTTP.API.Route.BearerToken (BearerToken(..))
22+import Yoga.HTTP.API.Route.Encoding (JSON, FormData, NoBody)
23+import Yoga.HTTP.API.Route.Handler (HandlerFn, Request, class SegmentPathParams, class SegmentQueryParams, class SegmentQueryParamsRL, class EncodingBody, class CaptureParams, class RequestHeaders, class RequestBody)
24+import Yoga.HTTP.API.Route.HeaderError (HeaderError(..))
25+import Yoga.HTTP.API.Route.HeaderValue (class HeaderValue, class HeaderValueType, headerValueType, parseHeader, printHeader)
26+import Yoga.HTTP.API.Route.Method (DELETE, GET, PATCH, POST, PUT)
27+import Yoga.HTTP.API.Route.OpenAPI (class CollectOperations, collectOperations, buildOpenAPISpec, buildOpenAPISpec', OpenAPISpec, ServerObject, class RenderHeadersSchema, class RenderHeadersSchemaRL, class RenderPathParamsSchema, class RenderPathParamsSchemaRL, class RenderQueryParamsSchema, class RenderQueryParamsSchemaRL, class RenderRequestBodySchema, class RenderResponseHeadersSchema, class RenderResponseHeadersSchemaRL, class RenderResponseSchema, class RenderVariantResponseSchemaRL, class RenderJSONSchema, class ToOpenAPI, renderHeadersSchema, renderHeadersSchemaRL, renderPathParamsSchema, renderPathParamsSchemaRL, renderQueryParamsSchema, renderQueryParamsSchemaRL, renderRequestBodySchema, renderResponseHeadersSchema, renderResponseHeadersSchemaRL, renderResponseSchema, renderVariantResponseSchemaRL, renderJSONSchema, toOpenAPI)
28+import Yoga.HTTP.API.Route.OpenAPIMetadata (class HasDescription, description, class HasExample, example, class HasFormat, format, class HasMinimum, minimum, class HasMaximum, maximum, class HasPattern, pattern, class HasMinLength, minLength, class HasMaxLength, maxLength, class HasTitle, title, class HasNullable, nullable, class HasDefault, default, class HasDeprecated, deprecated, class HasEnum, enum, class GenericEnumValues, genericEnumValues, class HasOperationMetadata, operationMetadata, OperationMetadata, Description, Example, Format, Minimum, Maximum, Pattern, MinLength, MaxLength, Title, Nullable, Default, Deprecated, Enum)
29+import Yoga.HTTP.API.Route.RenderMethod (class RenderMethod, renderMethod)
30+import Yoga.HTTP.API.Route.Response (Response(..), ResponseData, respondNoHeaders, respondWith)
31+import Yoga.HTTP.API.Route.Route (Route(..), route, class ConvertResponseVariant, class ConvertResponseVariantRL)
32+import Yoga.HTTP.API.Route.RouteHandler (Handler, class RouteHandler, mkHandler, runHandler)
33+import Yoga.HTTP.API.Route.StatusCode (StatusCode(..), class StatusCodeMap, statusCodeFor, statusCodeToString)
test/MetadataValidationTest.Spec.pursnew file+205
@@ -0,0 +1,205 @@
1+module MetadataValidationTest.Spec where
2+
3+import Prelude
4+
5+import Data.Either (Either(..), isLeft)
6+import Effect (Effect)
7+import Effect.Aff (Aff)
8+import Type.Function (type (#))
9+import Yoga.HTTP.API.Path (parseParam)
10+import Yoga.HTTP.API.Route.HeaderValue (parseHeader)
11+import Yoga.HTTP.API.Route.OpenAPIMetadata (Pattern, MinLength, MaxLength, Minimum, Maximum, Description, Example)
12+import ViTest (ViTest, describe, test)
13+import ViTest.Expect (expectToBe)
14+
15+expectToEqual :: forall a. Eq a => a -> a -> Aff Unit
16+expectToEqual expected actual = expectToBe true (expected == actual)
17+
18+expectLeft :: forall a b. Either a b -> Aff Unit
19+expectLeft = expectToBe true <<< isLeft
20+
21+--------------------------------------------------------------------------------
22+-- Pattern Validation Tests
23+--------------------------------------------------------------------------------
24+
25+testPatternValidation :: Effect ViTest
26+testPatternValidation = describe "Pattern Validation" $ do
27+ _ <- test "parseParam accepts matching string" do
28+ let result = parseParam "hello" :: Either String (String # Pattern "^[a-z]+$")
29+ expectToEqual (Right "hello") (map (const "hello") result)
30+
31+ _ <- test "parseParam rejects non-matching string" do
32+ let result = parseParam "Hello123" :: Either String (String # Pattern "^[a-z]+$")
33+ expectLeft result
34+
35+ _ <- test "parseParam error contains pattern" do
36+ let result = parseParam "123" :: Either String (String # Pattern "^[a-z]+$")
37+ case result of
38+ Left err -> expectToBe true (err == "Value '123' does not match pattern: ^[a-z]+$")
39+ Right _ -> expectToBe true false
40+
41+ _ <- test "parseHeader accepts matching string" do
42+ let result = parseHeader "hello" :: Either String (String # Pattern "^[a-z]+$")
43+ expectToEqual (Right "hello") (map (const "hello") result)
44+
45+ test "parseHeader rejects non-matching string" do
46+ let result = parseHeader "Hello123" :: Either String (String # Pattern "^[a-z]+$")
47+ expectLeft result
48+
49+--------------------------------------------------------------------------------
50+-- MinLength Validation Tests
51+--------------------------------------------------------------------------------
52+
53+testMinLengthValidation :: Effect ViTest
54+testMinLengthValidation = describe "MinLength Validation" $ do
55+ _ <- test "parseParam accepts string at minimum length" do
56+ let result = parseParam "abc" :: Either String (String # MinLength 3)
57+ expectToEqual (Right "abc") (map (const "abc") result)
58+
59+ _ <- test "parseParam accepts string above minimum length" do
60+ let result = parseParam "abcdef" :: Either String (String # MinLength 3)
61+ expectToEqual (Right "abcdef") (map (const "abcdef") result)
62+
63+ _ <- test "parseParam rejects string below minimum length" do
64+ let result = parseParam "ab" :: Either String (String # MinLength 3)
65+ expectLeft result
66+
67+ _ <- test "parseParam error message for short string" do
68+ let result = parseParam "ab" :: Either String (String # MinLength 3)
69+ case result of
70+ Left err -> expectToBe true (err == "String length 2 is less than minimum 3")
71+ Right _ -> expectToBe true false
72+
73+ test "parseHeader rejects string below minimum length" do
74+ let result = parseHeader "ab" :: Either String (String # MinLength 3)
75+ expectLeft result
76+
77+--------------------------------------------------------------------------------
78+-- MaxLength Validation Tests
79+--------------------------------------------------------------------------------
80+
81+testMaxLengthValidation :: Effect ViTest
82+testMaxLengthValidation = describe "MaxLength Validation" $ do
83+ _ <- test "parseParam accepts string at maximum length" do
84+ let result = parseParam "abc" :: Either String (String # MaxLength 3)
85+ expectToEqual (Right "abc") (map (const "abc") result)
86+
87+ _ <- test "parseParam accepts string below maximum length" do
88+ let result = parseParam "ab" :: Either String (String # MaxLength 3)
89+ expectToEqual (Right "ab") (map (const "ab") result)
90+
91+ _ <- test "parseParam rejects string above maximum length" do
92+ let result = parseParam "abcdef" :: Either String (String # MaxLength 3)
93+ expectLeft result
94+
95+ _ <- test "parseParam error message for long string" do
96+ let result = parseParam "abcdef" :: Either String (String # MaxLength 3)
97+ case result of
98+ Left err -> expectToBe true (err == "String length 6 exceeds maximum 3")
99+ Right _ -> expectToBe true false
100+
101+ test "parseHeader rejects string above maximum length" do
102+ let result = parseHeader "abcdef" :: Either String (String # MaxLength 3)
103+ expectLeft result
104+
105+--------------------------------------------------------------------------------
106+-- Minimum Validation Tests
107+--------------------------------------------------------------------------------
108+
109+testMinimumValidation :: Effect ViTest
110+testMinimumValidation = describe "Minimum Validation" $ do
111+ _ <- test "parseParam accepts value at minimum" do
112+ let result = parseParam "1" :: Either String (Int # Minimum 1)
113+ expectToEqual (Right 1) (map (const 1) result)
114+
115+ _ <- test "parseParam accepts value above minimum" do
116+ let result = parseParam "50" :: Either String (Int # Minimum 1)
117+ expectToEqual (Right 50) (map (const 50) result)
118+
119+ _ <- test "parseParam rejects value below minimum" do
120+ let result = parseParam "0" :: Either String (Int # Minimum 1)
121+ expectLeft result
122+
123+ _ <- test "parseParam error message for value below minimum" do
124+ let result = parseParam "0" :: Either String (Int # Minimum 1)
125+ case result of
126+ Left err -> expectToBe true (err == "Value 0 is less than minimum 1")
127+ Right _ -> expectToBe true false
128+
129+ _ <- test "inner parse failure propagates" do
130+ let result = parseParam "abc" :: Either String (Int # Minimum 1)
131+ expectLeft result
132+
133+ test "parseHeader rejects value below minimum" do
134+ let result = parseHeader "0" :: Either String (Int # Minimum 1)
135+ expectLeft result
136+
137+--------------------------------------------------------------------------------
138+-- Maximum Validation Tests
139+--------------------------------------------------------------------------------
140+
141+testMaximumValidation :: Effect ViTest
142+testMaximumValidation = describe "Maximum Validation" $ do
143+ _ <- test "parseParam accepts value at maximum" do
144+ let result = parseParam "100" :: Either String (Int # Maximum 100)
145+ expectToEqual (Right 100) (map (const 100) result)
146+
147+ _ <- test "parseParam accepts value below maximum" do
148+ let result = parseParam "50" :: Either String (Int # Maximum 100)
149+ expectToEqual (Right 50) (map (const 50) result)
150+
151+ _ <- test "parseParam rejects value above maximum" do
152+ let result = parseParam "150" :: Either String (Int # Maximum 100)
153+ expectLeft result
154+
155+ _ <- test "parseParam error message for value above maximum" do
156+ let result = parseParam "150" :: Either String (Int # Maximum 100)
157+ case result of
158+ Left err -> expectToBe true (err == "Value 150 exceeds maximum 100")
159+ Right _ -> expectToBe true false
160+
161+ test "parseHeader rejects value above maximum" do
162+ let result = parseHeader "150" :: Either String (Int # Maximum 100)
163+ expectLeft result
164+
165+--------------------------------------------------------------------------------
166+-- Composed Validation Tests
167+--------------------------------------------------------------------------------
168+
169+testComposedValidation :: Effect ViTest
170+testComposedValidation = describe "Composed Validation" $ do
171+ _ <- test "Int with Minimum and Maximum accepts valid value" do
172+ let result = parseParam "50" :: Either String (Int # Minimum 1 # Maximum 100)
173+ expectToEqual (Right 50) (map (const 50) result)
174+
175+ _ <- test "Int with Minimum and Maximum rejects below minimum" do
176+ let result = parseParam "0" :: Either String (Int # Minimum 1 # Maximum 100)
177+ expectLeft result
178+
179+ _ <- test "Int with Minimum and Maximum rejects above maximum" do
180+ let result = parseParam "150" :: Either String (Int # Minimum 1 # Maximum 100)
181+ expectLeft result
182+
183+ _ <- test "String with MinLength and MaxLength accepts valid string" do
184+ let result = parseParam "hello" :: Either String (String # MinLength 3 # MaxLength 10)
185+ expectToEqual (Right "hello") (map (const "hello") result)
186+
187+ _ <- test "String with MinLength and MaxLength rejects short string" do
188+ let result = parseParam "ab" :: Either String (String # MinLength 3 # MaxLength 10)
189+ expectLeft result
190+
191+ _ <- test "String with MinLength and MaxLength rejects long string" do
192+ let result = parseParam "this is too long" :: Either String (String # MinLength 3 # MaxLength 10)
193+ expectLeft result
194+
195+ _ <- test "String with Pattern and MinLength validates both" do
196+ let result = parseParam "ab" :: Either String (String # Pattern "^[a-z]+$" # MinLength 3)
197+ expectLeft result
198+
199+ _ <- test "documentary wrappers remain transparent" do
200+ let result = parseParam "42" :: Either String (Int # Description "user id" # Example "42" # Minimum 1)
201+ expectToEqual (Right 42) (map (const 42) result)
202+
203+ test "inner parse failure propagates through composed wrappers" do
204+ let result = parseParam "abc" :: Either String (Int # Minimum 1 # Maximum 100)
205+ expectLeft result
test/OperatorTest.Spec.pursnew file+30
@@ -0,0 +1,30 @@
1+module OperatorTest.Spec where
2+
3+import Prelude
4+
5+import Effect (Effect)
6+import Effect.Aff (Aff)
7+import Test.OperatorTest as Op
8+import Type.Proxy (Proxy(..))
9+import Yoga.HTTP.API.Path (Path, type (/), type (:), type (:?))
10+import ViTest (ViTest, describe, test)
11+import ViTest.Expect (expectToBe)
12+
13+-- Custom equality assertion that compares in PureScript then asserts true
14+expectToEqual :: forall a. Eq a => a -> a -> Aff Unit
15+expectToEqual expected actual = expectToBe true (expected == actual)
16+
17+-- Test rendering paths to OpenAPI format
18+testRendering :: Effect ViTest
19+testRendering = describe "Path Rendering" $ do
20+ _ <- test "renders simple path with capture" do
21+ let result = Op.renderSimplePath (Proxy :: Proxy (Path ("users" / "id" : Int / "posts")))
22+ result # expectToEqual "/users/{id}/posts"
23+
24+ _ <- test "renders path with query params" do
25+ let result = Op.renderFullPath (Proxy :: Proxy (Path ("api" / "posts") :? { page :: Int, sort :: String }))
26+ expectToEqual "/api/posts?page={page}&sort={sort}" result
27+
28+ test "renders complex path with captures and query params" do
29+ let result = Op.renderFullPath (Proxy :: Proxy (Path ("api" / "users" / "id" : Int / "posts") :? { limit :: Int, offset :: Int }))
30+ expectToEqual "/api/users/{id}/posts?limit={limit}&offset={offset}" result
test/OperatorTest.pursnew file+141
@@ -0,0 +1,141 @@
1+module Test.OperatorTest where
2+
3+import Prelude
4+
5+import Effect (Effect)
6+import Effect.Console (log)
7+import Type.Proxy (Proxy(..))
8+import Data.Symbol (class IsSymbol, reflectSymbol)
9+import Type.RowList (class RowToList, RowList, Cons, Nil)
10+import Data.String as String
11+
12+-- Import path types from production module
13+import Yoga.HTTP.API.Path (Path, PathCons, Param, QueryParams, type (/), type (:), type (:?))
14+
15+-- Test usage
16+type TestPath1 = "users" : Int
17+
18+type TestPath3 = Path ("users" / "id" : Int / "posts")
19+
20+-- Or simpler: just use the operator for params
21+type TestPath4 = Path ("users" / "id" : Int / "posts")
22+
23+-- Test usage examples with record-based query params
24+type TestPath5 = Path ("users" / "id" : Int) :? { limit :: Int }
25+
26+-- Use a multi-segment path for this example
27+type TestPath6 = Path ("api" / "posts") :? { page :: Int, sort :: String }
28+
29+-- More realistic example
30+type TestPath7 = Path ("api" / "users" / "id" : Int / "posts") :? { limit :: Int, offset :: Int, sort :: Boolean }
31+
32+-- Rendering paths to OpenAPI format
33+-- We need type classes to convert type-level structures to runtime strings
34+
35+-- Class to render path segments
36+-- Use instance chains to avoid overlapping instances
37+class RenderPathSegment :: forall k. k -> Constraint
38+class RenderPathSegment path where
39+ renderPathSegment :: Proxy path -> String
40+
41+-- PathCons: render left and right, concatenate (most specific, try first)
42+instance renderPathSegmentCons :: (RenderPathSegment l, RenderPathSegment r) => RenderPathSegment (PathCons l r) where
43+ renderPathSegment _ = renderPathSegment (Proxy :: Proxy l) <> renderPathSegment (Proxy :: Proxy r)
44+
45+-- Param: render as {name}
46+else instance renderPathSegmentParam :: IsSymbol name => RenderPathSegment (Param name ty) where
47+ renderPathSegment _ = "/{" <> reflectSymbol (Proxy :: Proxy name) <> "}"
48+
49+-- A single symbol becomes a path segment (fallback, try last)
50+else instance renderPathSegmentSymbol :: IsSymbol s => RenderPathSegment s where
51+ renderPathSegment _ = "/" <> reflectSymbol (Proxy :: Proxy s)
52+
53+-- Top-level class for rendering complete paths
54+class RenderPath :: forall k. k -> Constraint
55+class RenderPath path where
56+ renderPath :: Proxy path -> String
57+
58+-- Path wrapper - this is the main entry point
59+instance renderPathPath :: RenderPathSegment segments => RenderPath (Path segments) where
60+ renderPath _ = renderPathSegment (Proxy :: Proxy segments)
61+
62+-- Class to render query params
63+class RenderQueryParams :: Row Type -> Constraint
64+class RenderQueryParams params where
65+ renderQueryParams :: Proxy params -> Array String
66+
67+-- We'll need to use RowToList for this
68+
69+class RenderQueryParamsList :: RowList Type -> Constraint
70+class RenderQueryParamsList list where
71+ renderQueryParamsList :: Proxy list -> Array String
72+
73+instance renderQueryParamsListNil :: RenderQueryParamsList Nil where
74+ renderQueryParamsList _ = []
75+
76+instance renderQueryParamsListCons ::
77+ ( IsSymbol name
78+ , RenderQueryParamsList tail
79+ ) =>
80+ RenderQueryParamsList (Cons name ty tail) where
81+ renderQueryParamsList _ =
82+ [ reflectSymbol (Proxy :: Proxy name) ] <> renderQueryParamsList (Proxy :: Proxy tail)
83+
84+instance renderQueryParamsImpl ::
85+ ( RowToList params list
86+ , RenderQueryParamsList list
87+ ) =>
88+ RenderQueryParams params where
89+ renderQueryParams _ = renderQueryParamsList (Proxy :: Proxy list)
90+
91+-- Final rendering with query params
92+class RenderPathWithQuery :: forall k. k -> Row Type -> Constraint
93+class RenderPathWithQuery path params where
94+ renderPathWithQuery :: Proxy path -> Proxy params -> String
95+
96+instance renderPathWithQueryInstance ::
97+ ( RenderPath path
98+ , RenderQueryParams params
99+ ) =>
100+ RenderPathWithQuery path params where
101+ renderPathWithQuery pathProxy paramsProxy =
102+ let
103+ path = renderPath pathProxy
104+ queryParams = renderQueryParams paramsProxy
105+ queryString = case queryParams of
106+ [] -> ""
107+ params -> "?" <> String.joinWith "&" (map (\p -> p <> "={" <> p <> "}") params)
108+ in
109+ path <> queryString
110+
111+-- For paths without query params
112+renderSimplePath :: forall path. RenderPath path => Proxy path -> String
113+renderSimplePath = renderPath
114+
115+-- Helper to render QueryParams type (Record row → unwrap to row)
116+renderFullPath
117+ :: forall path params
118+ . RenderPathWithQuery path params
119+ => Proxy (QueryParams path (Record params))
120+ -> String
121+renderFullPath _ = renderPathWithQuery (Proxy :: Proxy path) (Proxy :: Proxy params)
122+
123+-- Test it!
124+test1 :: String
125+test1 = renderSimplePath (Proxy :: Proxy TestPath4)
126+
127+-- Should produce: "/users/id/{id}/posts"
128+
129+test2 :: String
130+test2 = renderFullPath (Proxy :: Proxy (Path ("api" / "posts") :? { page :: Int, sort :: String }))
131+
132+-- Should produce: "/api/posts?page={page}&sort={sort}"
133+
134+-- Main function to test the rendering
135+main :: Effect Unit
136+main = do
137+ log "Testing path rendering:"
138+ log $ "test1 (path with capture): " <> test1
139+ log $ "test2 (path with query params): " <> test2
140+ log $ "TestPath5: " <> renderFullPath (Proxy :: Proxy TestPath5)
141+ log $ "TestPath7: " <> renderFullPath (Proxy :: Proxy TestPath7)
test/ParserTest.Spec.pursnew file+111
@@ -0,0 +1,111 @@
1+module ParserTest.Spec where
2+
3+import Prelude
4+
5+import Data.Either (Either(..))
6+import Data.Maybe (Maybe(..))
7+import Effect (Effect)
8+import Effect.Aff (Aff)
9+import Test.ParserTest as Parser
10+import Type.Proxy (Proxy(..))
11+import Yoga.HTTP.API.Path (Path, Required, type (/), type (:), type (:?))
12+import ViTest (ViTest, describe, test)
13+import ViTest.Expect (expectToBe)
14+
15+-- Custom equality assertion that compares in PureScript then asserts true
16+expectToEqual :: forall a. Eq a => a -> a -> Aff Unit
17+expectToEqual expected actual = expectToBe true (expected == actual)
18+
19+-- Type aliases for tests
20+type TestPathSimple = "users" / "id" : Int / "posts"
21+type TestPathWithQuery = Path ("users" / "id" : Int / "posts") :? { limit :: Int, offset :: Int }
22+type TestPathWithRequired = Path ("users" / "id" : Int / "posts") :? { limit :: Required Int, offset :: Int }
23+type TestPathError = Path ("users" / "id" : Int / "posts") :? { limit :: Int }
24+
25+-- Test segment parsing
26+testSegmentParsing :: Effect ViTest
27+testSegmentParsing = describe "Segment Parsing" $ do
28+ _ <- test "matches literal segment" do
29+ let result = Parser.matchSegment (Proxy :: Proxy "users") "/users/124"
30+ expectToEqual (Just "/124") result
31+
32+ test "fails to match different segment" do
33+ let result = Parser.matchSegment (Proxy :: Proxy "posts") "/users/124"
34+ expectToEqual Nothing result
35+
36+-- Test capture parsing
37+testCaptureParsing :: Effect ViTest
38+testCaptureParsing = describe "Capture Parsing" $ do
39+ _ <- test "parses Int capture" do
40+ let result = Parser.parseCapture "/124/posts" :: Maybe { value :: Int, remaining :: String }
41+ expectToEqual (Just { value: 124, remaining: "/posts" }) result
42+
43+ _ <- test "parses String capture" do
44+ let result = Parser.parseCapture "/hello/world" :: Maybe { value :: String, remaining :: String }
45+ expectToEqual (Just { value: "hello", remaining: "/world" }) result
46+
47+ test "fails to parse invalid Int" do
48+ let result = Parser.parseCapture "/hello/world" :: Maybe { value :: Int, remaining :: String }
49+ expectToEqual Nothing result
50+
51+-- Test complete path parsing
52+testPathParsing :: Effect ViTest
53+testPathParsing = describe "Path Parsing" $ do
54+ _ <- test "parses path with capture" do
55+ let result = Parser.parsePathSegments (Proxy :: Proxy TestPathSimple) "/users/124/posts"
56+ expectToEqual (Just { captures: { id: 124 }, remaining: "" }) result
57+
58+ _ <- test "fails on invalid path" do
59+ let result = Parser.parsePathSegments (Proxy :: Proxy TestPathSimple) "/users/hello/posts"
60+ expectToEqual Nothing result
61+
62+ test "fails on wrong path structure" do
63+ let result = Parser.parsePathSegments (Proxy :: Proxy TestPathSimple) "/wrong/124/posts"
64+ expectToEqual Nothing result
65+
66+-- Test query parameter parsing (optional)
67+testOptionalQueryParams :: Effect ViTest
68+testOptionalQueryParams = describe "Optional Query Parameters" do
69+ _ <- test "parses all query params present" do
70+ let result = Parser.parseFullPath (Proxy :: Proxy TestPathWithQuery) (Proxy :: Proxy (limit :: Int, offset :: Int)) "/users/124/posts?limit=10&offset=20"
71+ expectToEqual (Right { path: { id: 124 }, query: { limit: Just 10, offset: Just 20 } }) result
72+
73+ _ <- test "parses with some query params missing" do
74+ let result = Parser.parseFullPath (Proxy :: Proxy TestPathWithQuery) (Proxy :: Proxy (limit :: Int, offset :: Int)) "/users/124/posts?limit=10"
75+ expectToEqual (Right { path: { id: 124 }, query: { limit: Just 10, offset: Nothing } }) result
76+
77+ test "parses with no query params" do
78+ let result = Parser.parseFullPath (Proxy :: Proxy TestPathWithQuery) (Proxy :: Proxy (limit :: Int, offset :: Int)) "/users/124/posts"
79+ expectToEqual (Right { path: { id: 124 }, query: { limit: Nothing, offset: Nothing } }) result
80+
81+-- Test required query parameters
82+testRequiredQueryParams :: Effect ViTest
83+testRequiredQueryParams = describe "Required Query Parameters" $ do
84+ _ <- test "parses required param as plain type" do
85+ let result = Parser.parseFullPath (Proxy :: Proxy TestPathWithRequired) (Proxy :: Proxy (limit :: Required Int, offset :: Int)) "/users/124/posts?limit=10&offset=20"
86+ expectToEqual (Right { path: { id: 124 }, query: { limit: 10, offset: Just 20 } }) result
87+
88+ _ <- test "succeeds when required param present, optional missing" do
89+ let result = Parser.parseFullPath (Proxy :: Proxy TestPathWithRequired) (Proxy :: Proxy (limit :: Required Int, offset :: Int)) "/users/124/posts?limit=10"
90+ expectToEqual (Right { path: { id: 124 }, query: { limit: 10, offset: Nothing } }) result
91+
92+ _ <- test "fails when required param missing" do
93+ let result = Parser.parseFullPath (Proxy :: Proxy TestPathWithRequired) (Proxy :: Proxy (limit :: Required Int, offset :: Int)) "/users/124/posts"
94+ expectToEqual (Left [ "Missing required query parameter: limit" ]) result
95+
96+ test "fails with descriptive error for missing required param" do
97+ let result = Parser.parseFullPath (Proxy :: Proxy TestPathWithRequired) (Proxy :: Proxy (limit :: Required Int, offset :: Int)) "/users/124/posts?offset=5"
98+ expectToEqual (Left [ "Missing required query parameter: limit" ]) result
99+
100+-- Test error cases
101+testErrorCases :: Effect ViTest
102+testErrorCases = describe "Error Handling" $ do
103+ _ <- test "returns error for invalid path structure" do
104+ let result = Parser.parseFullPath (Proxy :: Proxy TestPathError) (Proxy :: Proxy (limit :: Int)) "/invalid/path"
105+ case result of
106+ Left _ -> expectToBe true true
107+ Right _ -> expectToBe false true
108+
109+ test "handles invalid Int in capture" do
110+ let result = Parser.parsePathSegments (Proxy :: Proxy TestPathSimple) "/users/notanumber/posts"
111+ expectToEqual Nothing result
test/ParserTest.pursnew file+354
@@ -0,0 +1,354 @@
1+module Test.ParserTest where
2+
3+import Prelude
4+
5+import Data.Maybe (Maybe(..), fromMaybe)
6+import Data.Either (Either(..))
7+import Data.String (Pattern(..))
8+import Data.String as String
9+import Data.Int as Int
10+import Data.Array as Array
11+import Type.Proxy (Proxy(..))
12+import Data.Symbol (class IsSymbol, reflectSymbol)
13+import Prim.Row as Row
14+import Type.RowList (class RowToList, RowList, Cons, Nil)
15+import Record as Record
16+import Record.Builder as Builder
17+import Effect (Effect)
18+import Effect.Console (log, logShow)
19+
20+-- Import path types from production module
21+import Yoga.HTTP.API.Path (Path, PathCons, Param, QueryParams, Required, type (/), type (:), type (:?))
22+
23+-- Let's start with a simple example
24+-- Given: Path ("users" / "id" : Int / "posts")
25+-- Parse: "/users/124/posts"
26+-- Result: { id :: Int }
27+
28+-- First, let's try a really simple case: just one capture
29+type SimplePath = Path ("users" / "id" : Int)
30+
31+-- We need a typeclass that can parse a path string and extract the captures
32+class ParsePath :: forall k. k -> Type -> Constraint
33+class ParsePath path result | path -> result where
34+ parsePath :: Proxy path -> String -> Maybe result
35+
36+-- Start with the simplest possible case: a path with one segment and one capture
37+-- Path ("users" / "id" : Int)
38+-- We need to parse this step by step
39+
40+-- First, let's define what the result type should look like for different path structures
41+class PathResult :: forall k. k -> Type -> Constraint
42+class PathResult path result | path -> result
43+
44+-- For a Param, the result is just the value
45+instance pathResultParam :: PathResult (Param name ty) ty
46+
47+-- For a simple string segment followed by a param, we need to extract just the param
48+-- This is getting complex... let's think differently
49+
50+-- Let's use a simpler approach: define what segments we expect and parse them
51+class ParseSegment :: forall k. k -> Constraint
52+class ParseSegment segment where
53+ -- Returns Nothing if this segment doesn't match, Just remaining if it does
54+ matchSegment :: Proxy segment -> String -> Maybe String
55+
56+-- A literal string segment must match exactly
57+instance parseSegmentString :: IsSymbol s => ParseSegment s where
58+ matchSegment _ path =
59+ let
60+ segment = reflectSymbol (Proxy :: Proxy s)
61+ prefix = "/" <> segment
62+ in
63+ if String.take (String.length prefix) path == prefix then Just (String.drop (String.length prefix) path)
64+ else Nothing
65+
66+-- Now let's add parsing for captures
67+-- A capture should extract the next segment and try to parse it as the given type
68+class ParseCapture :: Type -> Constraint
69+class ParseCapture ty where
70+ -- Parse a capture from the path, returns (parsed value, remaining path)
71+ parseCapture :: String -> Maybe { value :: ty, remaining :: String }
72+
73+-- For Int, parse until the next / or end of string
74+instance parseCaptureInt :: ParseCapture Int where
75+ parseCapture path =
76+ let
77+ -- Skip leading /
78+ path' = if String.take 1 path == "/" then String.drop 1 path else path
79+ -- Take until next / or end
80+ segment = case String.indexOf (String.Pattern "/") path' of
81+ Just idx -> String.take idx path'
82+ Nothing -> path'
83+ remaining = String.drop (String.length segment) path'
84+ in
85+ case Int.fromString segment of
86+ Just value -> Just { value, remaining }
87+ Nothing -> Nothing
88+
89+-- For String, just take the next segment
90+instance parseCaptureString :: ParseCapture String where
91+ parseCapture path =
92+ let
93+ path' = if String.take 1 path == "/" then String.drop 1 path else path
94+ segment = case String.indexOf (String.Pattern "/") path' of
95+ Just idx -> String.take idx path'
96+ Nothing -> path'
97+ remaining = String.drop (String.length segment) path'
98+ in
99+ Just { value: segment, remaining }
100+
101+-- Test the simple case first
102+test1 :: Maybe String
103+test1 = matchSegment (Proxy :: Proxy "users") "/users/124"
104+
105+-- Should return: Just "/124"
106+
107+test2 :: Maybe String
108+test2 = matchSegment (Proxy :: Proxy "posts") "/users/124"
109+
110+-- Should return: Nothing
111+
112+test3 :: Maybe { value :: Int, remaining :: String }
113+test3 = parseCapture "/124/posts"
114+
115+-- Should return: Just { value: 124, remaining: "/posts" }
116+
117+test4 :: Maybe { value :: String, remaining :: String }
118+test4 = parseCapture "/hello/world"
119+
120+-- Should return: Just { value: "hello", remaining: "/world" }
121+
122+-- Now let's parse a complete path into a record
123+-- For Path ("users" / "id" : Int / "posts"), we want to extract { id :: Int }
124+
125+-- We need a typeclass that builds up a record from path segments
126+-- Use instance chains to avoid overlapping
127+class ParsePathSegments :: forall k. k -> Row Type -> Constraint
128+class ParsePathSegments segments result | segments -> result where
129+ parsePathSegments :: Proxy segments -> String -> Maybe { captures :: Record result, remaining :: String }
130+
131+-- PathCons: parse left, then parse right, merge the records (most specific, try first)
132+instance parsePathSegmentsCons ::
133+ ( ParsePathSegments l rowL
134+ , ParsePathSegments r rowR
135+ , Row.Union rowL rowR result
136+ , Row.Nub result result -- Remove duplicates
137+ ) =>
138+ ParsePathSegments (PathCons l r) result where
139+ parsePathSegments _ path = do
140+ { captures: capturesL, remaining: remaining1 } <- parsePathSegments (Proxy :: Proxy l) path
141+ { captures: capturesR, remaining: remaining2 } <- parsePathSegments (Proxy :: Proxy r) remaining1
142+ pure { captures: Record.merge capturesL capturesR, remaining: remaining2 }
143+
144+-- A Param captures a value and adds it to the record
145+else instance parsePathSegmentsParam ::
146+ ( IsSymbol name
147+ , ParseCapture ty
148+ , Row.Cons name ty () row
149+ , Row.Lacks name ()
150+ ) =>
151+ ParsePathSegments (Param name ty) row where
152+ parsePathSegments _ path =
153+ case parseCapture path of
154+ Just { value, remaining } ->
155+ let
156+ captures = Builder.build (Builder.insert (Proxy :: Proxy name) value) {}
157+ in
158+ Just { captures, remaining }
159+ Nothing -> Nothing
160+
161+-- Base case: a literal string segment (no captures, fallback)
162+else instance parsePathSegmentsString :: IsSymbol s => ParsePathSegments s () where
163+ parsePathSegments _ path =
164+ case matchSegment (Proxy :: Proxy s) path of
165+ Just remaining -> Just { captures: {}, remaining }
166+ Nothing -> Nothing
167+
168+-- Now test a real path!
169+type TestPath = "users" / "id" : Int / "posts"
170+
171+test5 :: Maybe { captures :: { id :: Int }, remaining :: String }
172+test5 = parsePathSegments (Proxy :: Proxy TestPath) "/users/124/posts"
173+
174+-- Should return: Just { captures: { id: 124 }, remaining: "" }
175+
176+test6 :: Maybe { captures :: { id :: Int }, remaining :: String }
177+test6 = parsePathSegments (Proxy :: Proxy TestPath) "/users/hello/posts"
178+
179+-- Should return: Nothing (can't parse "hello" as Int)
180+
181+-- Now let's add query parameter parsing
182+-- Query params can be optional (Maybe values) or required (Required wrapper)
183+-- Required is imported from Yoga.Fastify.Om.Path
184+
185+-- Helper to parse query string into key-value pairs
186+parseQueryString :: String -> Array { key :: String, value :: String }
187+parseQueryString queryString =
188+ let
189+ -- Remove leading "?" if present
190+ qs = if String.take 1 queryString == "?" then String.drop 1 queryString else queryString
191+ pairs = String.split (Pattern "&") qs
192+ in
193+ pairs # Array.mapMaybe \pair ->
194+ case String.indexOf (Pattern "=") pair of
195+ Just idx ->
196+ let
197+ key = String.take idx pair
198+ value = String.drop (idx + 1) pair
199+ in
200+ Just { key, value }
201+ Nothing -> Nothing
202+
203+-- Parse a specific query param by name
204+parseQueryParam :: forall ty. ParseCapture ty => String -> String -> Maybe ty
205+parseQueryParam queryString paramName =
206+ let
207+ pairs = parseQueryString queryString
208+ in
209+ case Array.find (\p -> p.key == paramName) pairs of
210+ Just { value } -> map _.value (parseCapture ("/" <> value))
211+ Nothing -> Nothing
212+
213+-- Build a record of query params (Required becomes plain type, others become Maybe)
214+-- Returns Either with missing required params as errors
215+class ParseQueryParams :: Row Type -> Row Type -> Constraint
216+class ParseQueryParams params result | params -> result where
217+ parseQueryParams :: Proxy params -> String -> Either (Array String) (Record result)
218+
219+-- We need to handle Required vs optional params differently
220+-- This requires RowToList to iterate over the params
221+class ParseQueryParamsList :: RowList Type -> Row Type -> Constraint
222+class ParseQueryParamsList list result | list -> result where
223+ parseQueryParamsList :: Proxy list -> String -> Either (Array String) (Record result)
224+
225+instance parseQueryParamsListNil :: ParseQueryParamsList Nil () where
226+ parseQueryParamsList _ _ = Right {}
227+
228+-- Required param: must be present or we error
229+instance parseQueryParamsListConsRequired ::
230+ ( IsSymbol name
231+ , ParseCapture ty
232+ , ParseQueryParamsList tail tailResult
233+ , Row.Cons name ty tailResult result
234+ , Row.Lacks name tailResult
235+ ) =>
236+ ParseQueryParamsList (Cons name (Required ty) tail) result where
237+ parseQueryParamsList _ queryString =
238+ let
239+ paramName = reflectSymbol (Proxy :: Proxy name)
240+ value = parseQueryParam queryString paramName
241+ restResult = parseQueryParamsList (Proxy :: Proxy tail) queryString
242+ in
243+ case value, restResult of
244+ Just v, Right rest -> Right $ Builder.build (Builder.insert (Proxy :: Proxy name) v) rest
245+ Nothing, Right _ -> Left [ "Missing required query parameter: " <> paramName ]
246+ Just _, Left errs -> Left errs
247+ Nothing, Left errs -> Left ([ "Missing required query parameter: " <> paramName ] <> errs)
248+
249+-- Optional param: always succeeds with Maybe
250+else instance parseQueryParamsListConsOptional ::
251+ ( IsSymbol name
252+ , ParseCapture ty
253+ , ParseQueryParamsList tail tailResult
254+ , Row.Cons name (Maybe ty) tailResult result
255+ , Row.Lacks name tailResult
256+ ) =>
257+ ParseQueryParamsList (Cons name ty tail) result where
258+ parseQueryParamsList _ queryString =
259+ let
260+ paramName = reflectSymbol (Proxy :: Proxy name)
261+ value = parseQueryParam queryString paramName
262+ restResult = parseQueryParamsList (Proxy :: Proxy tail) queryString
263+ in
264+ case restResult of
265+ Right rest -> Right $ Builder.build (Builder.insert (Proxy :: Proxy name) value) rest
266+ Left errs -> Left errs
267+
268+instance parseQueryParamsImpl ::
269+ ( RowToList params list
270+ , ParseQueryParamsList list result
271+ ) =>
272+ ParseQueryParams params result where
273+ parseQueryParams _ = parseQueryParamsList (Proxy :: Proxy list)
274+
275+-- Now parse a complete path with query params
276+-- Returns Either with errors for invalid paths or missing required query params
277+class ParseFullPath :: forall k. k -> Row Type -> Row Type -> Row Type -> Constraint
278+class ParseFullPath path queryParams pathResult queryResult | path queryParams -> pathResult queryResult where
279+ parseFullPath :: Proxy path -> Proxy queryParams -> String -> Either (Array String) { path :: Record pathResult, query :: Record queryResult }
280+
281+instance parseFullPathImpl ::
282+ ( ParsePathSegments segments pathResult
283+ , ParseQueryParams queryParams queryResult
284+ ) =>
285+ ParseFullPath (QueryParams (Path segments) (Record queryParams)) queryParams pathResult queryResult where
286+ parseFullPath _ _ input =
287+ let
288+ -- Split on ? to separate path and query
289+ parts = String.split (Pattern "?") input
290+ pathPart = Array.head parts # fromMaybe ""
291+ queryPart = Array.index parts 1 # fromMaybe ""
292+ in
293+ case parsePathSegments (Proxy :: Proxy segments) pathPart of
294+ Just { captures: pathCaptures, remaining: "" } ->
295+ case parseQueryParams (Proxy :: Proxy queryParams) queryPart of
296+ Right query -> Right { path: pathCaptures, query }
297+ Left errs -> Left errs
298+ _ -> Left [ "Invalid path: " <> pathPart ]
299+
300+-- Test with optional query params
301+type TestPathWithQuery = Path ("users" / "id" : Int / "posts") :? { limit :: Int, offset :: Int }
302+
303+test7 :: Either (Array String) { path :: { id :: Int }, query :: { limit :: Maybe Int, offset :: Maybe Int } }
304+test7 = parseFullPath (Proxy :: Proxy TestPathWithQuery) (Proxy :: Proxy (limit :: Int, offset :: Int)) "/users/124/posts?limit=10&offset=20"
305+
306+-- Should return: Right { path: { id: 124 }, query: { limit: Just 10, offset: Just 20 } }
307+
308+test8 :: Either (Array String) { path :: { id :: Int }, query :: { limit :: Maybe Int, offset :: Maybe Int } }
309+test8 = parseFullPath (Proxy :: Proxy TestPathWithQuery) (Proxy :: Proxy (limit :: Int, offset :: Int)) "/users/124/posts?limit=10"
310+
311+-- Should return: Right { path: { id: 124 }, query: { limit: Just 10, offset: Nothing } }
312+
313+test9 :: Either (Array String) { path :: { id :: Int }, query :: { limit :: Maybe Int, offset :: Maybe Int } }
314+test9 = parseFullPath (Proxy :: Proxy TestPathWithQuery) (Proxy :: Proxy (limit :: Int, offset :: Int)) "/users/124/posts"
315+
316+-- Should return: Right { path: { id: 124 }, query: { limit: Nothing, offset: Nothing } }
317+
318+-- Test with Required query params
319+type TestPathWithRequired = Path ("users" / "id" : Int / "posts") :? { limit :: Required Int, offset :: Int }
320+
321+test10 :: Either (Array String) { path :: { id :: Int }, query :: { limit :: Int, offset :: Maybe Int } }
322+test10 = parseFullPath (Proxy :: Proxy TestPathWithRequired) (Proxy :: Proxy (limit :: Required Int, offset :: Int)) "/users/124/posts?limit=10&offset=20"
323+
324+-- Should return: Right { path: { id: 124 }, query: { limit: 10, offset: Just 20 } }
325+
326+test11 :: Either (Array String) { path :: { id :: Int }, query :: { limit :: Int, offset :: Maybe Int } }
327+test11 = parseFullPath (Proxy :: Proxy TestPathWithRequired) (Proxy :: Proxy (limit :: Required Int, offset :: Int)) "/users/124/posts?limit=10"
328+
329+-- Should return: Right { path: { id: 124 }, query: { limit: 10, offset: Nothing } }
330+
331+test12 :: Either (Array String) { path :: { id :: Int }, query :: { limit :: Int, offset :: Maybe Int } }
332+test12 = parseFullPath (Proxy :: Proxy TestPathWithRequired) (Proxy :: Proxy (limit :: Required Int, offset :: Int)) "/users/124/posts"
333+
334+-- Should return: Left ["Missing required query parameter: limit"]
335+
336+main :: Effect Unit
337+main = do
338+ log "Testing segment parsing:"
339+ logShow $ "matchSegment 'users' '/users/124': " <> show test1
340+ logShow $ "matchSegment 'posts' '/users/124': " <> show test2
341+ log "\nTesting capture parsing:"
342+ logShow $ "parseCapture Int '/124/posts': " <> show test3
343+ logShow $ "parseCapture String '/hello/world': " <> show test4
344+ log "\nTesting complete path parsing:"
345+ logShow $ "parse '/users/124/posts': " <> show test5
346+ logShow $ "parse '/users/hello/posts' (should fail): " <> show test6
347+ log "\nTesting path with optional query params:"
348+ logShow $ "parse '/users/124/posts?limit=10&offset=20': " <> show test7
349+ logShow $ "parse '/users/124/posts?limit=10': " <> show test8
350+ logShow $ "parse '/users/124/posts': " <> show test9
351+ log "\nTesting path with Required query params:"
352+ logShow $ "parse '/users/124/posts?limit=10&offset=20': " <> show test10
353+ logShow $ "parse '/users/124/posts?limit=10': " <> show test11
354+ logShow $ "parse '/users/124/posts' (should error): " <> show test12
test/Test.Operators.pursnew file+37
@@ -0,0 +1,37 @@
1+module Test.Operators where
2+
3+import Prelude
4+import Effect (Effect)
5+import ViTest (ViTest, viTest)
6+import OperatorTest.Spec as OperatorTest
7+import ParserTest.Spec as ParserTest
8+import VariantResponseTest.Spec as VariantResponseTest
9+import MetadataValidationTest.Spec as MetadataValidationTest
10+
11+spec :: Effect ViTest
12+spec = do
13+ _ <- OperatorTest.testRendering
14+ _ <- ParserTest.testSegmentParsing
15+ _ <- ParserTest.testCaptureParsing
16+ _ <- ParserTest.testPathParsing
17+ _ <- ParserTest.testOptionalQueryParams
18+ _ <- ParserTest.testRequiredQueryParams
19+ _ <- ParserTest.testErrorCases
20+ _ <- VariantResponseTest.testStatusCodeMapping
21+ _ <- VariantResponseTest.testStatusCodeToString
22+ _ <- VariantResponseTest.testRespondNoHeaders
23+ _ <- VariantResponseTest.testRespondWith
24+ _ <- VariantResponseTest.testRespond
25+ _ <- VariantResponseTest.testSimpleVariantOpenAPI
26+ _ <- VariantResponseTest.testComplexVariantOpenAPI
27+ _ <- VariantResponseTest.testVariantWithHeaders
28+ _ <- VariantResponseTest.testVariantPatternMatching
29+ _ <- MetadataValidationTest.testPatternValidation
30+ _ <- MetadataValidationTest.testMinLengthValidation
31+ _ <- MetadataValidationTest.testMaxLengthValidation
32+ _ <- MetadataValidationTest.testMinimumValidation
33+ _ <- MetadataValidationTest.testMaximumValidation
34+ MetadataValidationTest.testComposedValidation
35+
36+main :: ViTest
37+main = viTest spec
test/VariantResponseTest.Spec.pursnew file+349
@@ -0,0 +1,349 @@
1+module VariantResponseTest.Spec where
2+
3+import Prelude
4+
5+import Data.String as String
6+import Data.Variant (Variant)
7+import Data.Variant as Variant
8+import Effect (Effect)
9+import Effect.Aff (Aff)
10+import Type.Proxy (Proxy(..))
11+import Yoga.HTTP.API.Route.StatusCode (StatusCode(..))
12+import Yoga.HTTP.API.Path (Root)
13+import Yoga.HTTP.API.Route (GET, POST, PUT, Route, Request, Response(..), respondNoHeaders, respondWith, toOpenAPI, statusCodeFor, statusCodeToString)
14+import Yoga.HTTP.API.Route.Response (respond) as Response
15+import ViTest (ViTest, describe, test)
16+import ViTest.Expect (expectToBe)
17+
18+-- Custom equality assertion that compares in PureScript then asserts true
19+expectToEqual :: forall a. Eq a => a -> a -> Aff Unit
20+expectToEqual expected actual = expectToBe true (expected == actual)
21+
22+--------------------------------------------------------------------------------
23+-- Type Definitions - Test that variant-based routes compile correctly
24+--------------------------------------------------------------------------------
25+
26+-- Simple variant route with ok and notFound responses
27+type SimpleVariantRoute = Route GET Root
28+ (Request {})
29+ ( ok :: { body :: String }
30+ , notFound :: { body :: String }
31+ )
32+
33+-- Variant route with multiple status codes
34+type MultiStatusRoute = Route POST Root
35+ (Request { headers :: { authorization :: String } })
36+ ( created :: { headers :: { "Location" :: String }, body :: User }
37+ , badRequest :: { body :: ErrorMessage }
38+ , unauthorized :: { body :: ErrorMessage }
39+ )
40+
41+-- Variant route with many response types
42+type ComplexVariantRoute = Route PUT Root
43+ (Request {})
44+ ( ok :: { body :: User }
45+ , created :: { headers :: { "Location" :: String }, body :: User }
46+ , badRequest :: { body :: ErrorMessage }
47+ , notFound :: { body :: ErrorMessage }
48+ , internalServerError :: { body :: ErrorMessage }
49+ )
50+
51+-- Example types for testing
52+type User = { id :: Int, name :: String }
53+type ErrorMessage = { error :: String }
54+
55+--------------------------------------------------------------------------------
56+-- Status Code Mapping Tests
57+--------------------------------------------------------------------------------
58+
59+testStatusCodeMapping :: Effect ViTest
60+testStatusCodeMapping = describe "StatusCodeMap" $ do
61+ _ <- test "ok maps to 200" do
62+ let statusCode = statusCodeFor (Proxy :: _ "ok")
63+ expectToEqual "200" (statusCodeToString statusCode)
64+
65+ _ <- test "created maps to 201" do
66+ let statusCode = statusCodeFor (Proxy :: _ "created")
67+ expectToEqual "201" (statusCodeToString statusCode)
68+
69+ _ <- test "accepted maps to 202" do
70+ let statusCode = statusCodeFor (Proxy :: _ "accepted")
71+ expectToEqual "202" (statusCodeToString statusCode)
72+
73+ _ <- test "noContent maps to 204" do
74+ let statusCode = statusCodeFor (Proxy :: _ "noContent")
75+ expectToEqual "204" (statusCodeToString statusCode)
76+
77+ _ <- test "badRequest maps to 400" do
78+ let statusCode = statusCodeFor (Proxy :: _ "badRequest")
79+ expectToEqual "400" (statusCodeToString statusCode)
80+
81+ _ <- test "unauthorized maps to 401" do
82+ let statusCode = statusCodeFor (Proxy :: _ "unauthorized")
83+ expectToEqual "401" (statusCodeToString statusCode)
84+
85+ _ <- test "forbidden maps to 403" do
86+ let statusCode = statusCodeFor (Proxy :: _ "forbidden")
87+ expectToEqual "403" (statusCodeToString statusCode)
88+
89+ _ <- test "notFound maps to 404" do
90+ let statusCode = statusCodeFor (Proxy :: _ "notFound")
91+ expectToEqual "404" (statusCodeToString statusCode)
92+
93+ _ <- test "conflict maps to 409" do
94+ let statusCode = statusCodeFor (Proxy :: _ "conflict")
95+ expectToEqual "409" (statusCodeToString statusCode)
96+
97+ _ <- test "unprocessableEntity maps to 422" do
98+ let statusCode = statusCodeFor (Proxy :: _ "unprocessableEntity")
99+ expectToEqual "422" (statusCodeToString statusCode)
100+
101+ _ <- test "internalServerError maps to 500" do
102+ let statusCode = statusCodeFor (Proxy :: _ "internalServerError")
103+ expectToEqual "500" (statusCodeToString statusCode)
104+
105+ _ <- test "notImplemented maps to 501" do
106+ let statusCode = statusCodeFor (Proxy :: _ "notImplemented")
107+ expectToEqual "501" (statusCodeToString statusCode)
108+
109+ _ <- test "badGateway maps to 502" do
110+ let statusCode = statusCodeFor (Proxy :: _ "badGateway")
111+ expectToEqual "502" (statusCodeToString statusCode)
112+
113+ test "serviceUnavailable maps to 503" do
114+ let statusCode = statusCodeFor (Proxy :: _ "serviceUnavailable")
115+ expectToEqual "503" (statusCodeToString statusCode)
116+
117+testStatusCodeToString :: Effect ViTest
118+testStatusCodeToString = describe "statusCodeToString" $ do
119+ _ <- test "converts 200 to string" do
120+ let result = statusCodeToString (StatusCode 200)
121+ expectToEqual "200" result
122+
123+ _ <- test "converts 404 to string" do
124+ let result = statusCodeToString (StatusCode 404)
125+ expectToEqual "404" result
126+
127+ test "converts 500 to string" do
128+ let result = statusCodeToString (StatusCode 500)
129+ expectToEqual "500" result
130+
131+--------------------------------------------------------------------------------
132+-- Response Construction Tests
133+--------------------------------------------------------------------------------
134+
135+testRespondNoHeaders :: Effect ViTest
136+testRespondNoHeaders = describe "respondNoHeaders" $ do
137+ _ <- test "constructs ok response with body" do
138+ let
139+ response :: Variant (ok :: Response () String, notFound :: Response () String)
140+ response = respondNoHeaders @"ok" "Success message"
141+ result = Variant.match
142+ { ok: \(Response rd) -> rd.body
143+ , notFound: \_ -> "Wrong variant!"
144+ }
145+ response
146+ expectToEqual "Success message" result
147+
148+ _ <- test "constructs notFound response with body" do
149+ let
150+ response :: Variant (ok :: Response () String, notFound :: Response () String)
151+ response = respondNoHeaders @"notFound" "Not found"
152+ result = Variant.match
153+ { ok: \_ -> "Wrong variant!"
154+ , notFound: \(Response rd) -> rd.body
155+ }
156+ response
157+ expectToEqual "Not found" result
158+
159+ test "response has empty headers" do
160+ let
161+ response :: Variant (ok :: Response () String)
162+ response = respondNoHeaders @"ok" "Test"
163+ result = Variant.match
164+ { ok: \(Response rd) -> rd.headers
165+ }
166+ response
167+ expectToEqual {} result
168+
169+testRespondWith :: Effect ViTest
170+testRespondWith = describe "respondWith" $ do
171+ _ <- test "constructs response with headers and body" do
172+ let
173+ response :: Variant (created :: Response ("Location" :: String) User)
174+ response = respondWith (Proxy :: _ "created")
175+ { "Location": "/users/123" }
176+ { id: 123, name: "Alice" }
177+ result = Variant.match
178+ { created: \(Response rd) -> rd.body.id
179+ }
180+ response
181+ expectToEqual 123 result
182+
183+ _ <- test "includes headers in response" do
184+ let
185+ response :: Variant (created :: Response ("Location" :: String) User)
186+ response = respondWith (Proxy :: _ "created")
187+ { "Location": "/users/456" }
188+ { id: 456, name: "Bob" }
189+ result = Variant.match
190+ { created: \(Response rd) -> rd.headers."Location"
191+ }
192+ response
193+ expectToEqual "/users/456" result
194+
195+ test "constructs response with multiple headers" do
196+ let
197+ response :: Variant (ok :: Response ("X-Request-Id" :: String, "X-Version" :: String) String)
198+ response = respondWith (Proxy :: _ "ok")
199+ { "X-Request-Id": "req-123"
200+ , "X-Version": "v1"
201+ }
202+ "Response body"
203+ reqId = Variant.match
204+ { ok: \(Response rd) -> rd.headers."X-Request-Id"
205+ }
206+ response
207+ version = Variant.match
208+ { ok: \(Response rd) -> rd.headers."X-Version"
209+ }
210+ response
211+ expectToBe true (reqId == "req-123" && version == "v1")
212+
213+testRespond :: Effect ViTest
214+testRespond = describe "respond" $ do
215+ test "constructs response from Response record" do
216+ let
217+ responseData :: Response ("Location" :: String) User
218+ responseData = Response
219+ { headers: { "Location": "/users/789" }
220+ , body: { id: 789, name: "Charlie" }
221+ }
222+
223+ response :: Variant (created :: Response ("Location" :: String) User)
224+ response = Response.respond (Proxy :: _ "created") responseData
225+ userId = Variant.match
226+ { created: \(Response rd) -> rd.body.id
227+ }
228+ response
229+ location = Variant.match
230+ { created: \(Response rd) -> rd.headers."Location"
231+ }
232+ response
233+ expectToBe true (userId == 789 && location == "/users/789")
234+
235+--------------------------------------------------------------------------------
236+-- OpenAPI Generation Tests
237+--------------------------------------------------------------------------------
238+
239+testSimpleVariantOpenAPI :: Effect ViTest
240+testSimpleVariantOpenAPI = describe "OpenAPI Generation - Simple Variant" $ do
241+ _ <- test "generates OpenAPI with multiple status codes" do
242+ let
243+ result = toOpenAPI
244+ @( Route GET Root
245+ (Request {})
246+ ( ok :: { body :: String }
247+ , notFound :: { body :: String }
248+ )
249+ )
250+ -- Verify contains both 200 and 404
251+ expectToBe true (String.contains (String.Pattern "200") result)
252+ expectToBe true (String.contains (String.Pattern "404") result)
253+
254+ test "contains response structure" do
255+ let
256+ result = toOpenAPI @SimpleVariantRoute
257+ -- Verify OpenAPI structure
258+ expectToBe true (String.contains (String.Pattern "parameters") result)
259+ expectToBe true (String.contains (String.Pattern "responses") result)
260+ expectToBe true (String.contains (String.Pattern "Successful response") result)
261+
262+testComplexVariantOpenAPI :: Effect ViTest
263+testComplexVariantOpenAPI = describe "OpenAPI Generation - Complex Variant" $ do
264+ _ <- test "generates OpenAPI for route with 3 status codes" do
265+ let
266+ result = toOpenAPI
267+ @( Route POST Root
268+ (Request { headers :: { authorization :: String } })
269+ ( created :: { headers :: { "Location" :: String }, body :: User }
270+ , badRequest :: { body :: ErrorMessage }
271+ , unauthorized :: { body :: ErrorMessage }
272+ )
273+ )
274+ -- Verify contains 201, 400, and 401
275+ expectToBe true (String.contains (String.Pattern "201") result)
276+ expectToBe true (String.contains (String.Pattern "400") result)
277+ expectToBe true (String.contains (String.Pattern "401") result)
278+
279+ _ <- test "includes request parameters" do
280+ let
281+ result = toOpenAPI @MultiStatusRoute
282+ -- Verify includes authorization header parameter
283+ expectToBe true (String.contains (String.Pattern "authorization") result)
284+ expectToBe true (String.contains (String.Pattern "header") result)
285+
286+ test "generates OpenAPI for route with 5 status codes" do
287+ let
288+ result = toOpenAPI @ComplexVariantRoute
289+ -- Verify contains all status codes
290+ expectToBe true (String.contains (String.Pattern "200") result)
291+ expectToBe true (String.contains (String.Pattern "201") result)
292+ expectToBe true (String.contains (String.Pattern "400") result)
293+ expectToBe true (String.contains (String.Pattern "404") result)
294+ expectToBe true (String.contains (String.Pattern "500") result)
295+
296+testVariantWithHeaders :: Effect ViTest
297+testVariantWithHeaders = describe "OpenAPI Generation - Variant with Response Headers" $ do
298+ test "includes response headers in OpenAPI" do
299+ let
300+ result = toOpenAPI
301+ @( Route POST Root
302+ (Request {})
303+ ( created :: { headers :: { "Location" :: String, "X-Request-Id" :: String }, body :: User }
304+ )
305+ )
306+ -- Verify includes Location and X-Request-Id in response headers
307+ expectToBe true (String.contains (String.Pattern "Location") result)
308+ expectToBe true (String.contains (String.Pattern "X-Request-Id") result)
309+ expectToBe true (String.contains (String.Pattern "201") result)
310+
311+--------------------------------------------------------------------------------
312+-- Integration Tests
313+--------------------------------------------------------------------------------
314+
315+testVariantPatternMatching :: Effect ViTest
316+testVariantPatternMatching = describe "Variant Pattern Matching" $ do
317+ _ <- test "can pattern match on ok variant" do
318+ let
319+ response :: Variant (ok :: Response () String, notFound :: Response () String)
320+ response = respondNoHeaders @"ok" "Success"
321+ result = Variant.match
322+ { ok: \_ -> "matched ok"
323+ , notFound: \_ -> "matched notFound"
324+ }
325+ response
326+ expectToEqual "matched ok" result
327+
328+ _ <- test "can pattern match on notFound variant" do
329+ let
330+ response :: Variant (ok :: Response () String, notFound :: Response () String)
331+ response = respondNoHeaders @"notFound" "Not found"
332+ result = Variant.match
333+ { ok: \_ -> "matched ok"
334+ , notFound: \_ -> "matched notFound"
335+ }
336+ response
337+ expectToEqual "matched notFound" result
338+
339+ test "can match all cases with match" do
340+ let
341+ response :: Variant (ok :: Response () String, notFound :: Response () String, badRequest :: Response () String)
342+ response = respondNoHeaders @"badRequest" "Bad request"
343+ result = Variant.match
344+ { ok: \_ -> "matched ok"
345+ , notFound: \_ -> "matched notFound"
346+ , badRequest: \_ -> "matched badRequest"
347+ }
348+ response
349+ expectToEqual "matched badRequest" result
vitest.config.jsnew file+9
@@ -0,0 +1,9 @@
1+import { defineConfig } from "vitest/config";
2+
3+export default defineConfig({
4+ test: {
5+ include: ["output/Test.Operators/index.js"],
6+ globals: true,
7+ environment: "jsdom",
8+ },
9+});