Static site hosting via tangled

Initial commit

Grace Kind aa106a03

+5
.example.env
··· 1 + # fill in and rename to .env 2 + # note these aren't secrets, just config 3 + KNOT_DOMAIN = "knot.gracekind.net" 4 + OWNER_DID = "did:plc:p572wxnsuoogcrhlfrlizlrb" 5 + REPO_NAME = "static-site-example"
+4
.gitignore
··· 1 + node_modules 2 + .claude 3 + .env 4 + .wrangler
+1
.nvmrc
··· 1 + 24
+2512
package-lock.json
··· 1 + { 2 + "name": "tangled-pages", 3 + "version": "1.0.0", 4 + "lockfileVersion": 3, 5 + "requires": true, 6 + "packages": { 7 + "": { 8 + "name": "tangled-pages", 9 + "version": "1.0.0", 10 + "dependencies": { 11 + "dotenv": "^17.2.1", 12 + "express": "^5.1.0", 13 + "nodemon": "^3.1.10", 14 + "wrangler": "^4.33.0", 15 + "yaml": "^2.8.1" 16 + } 17 + }, 18 + "node_modules/@cloudflare/kv-asset-handler": { 19 + "version": "0.4.0", 20 + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.0.tgz", 21 + "integrity": "sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==", 22 + "license": "MIT OR Apache-2.0", 23 + "dependencies": { 24 + "mime": "^3.0.0" 25 + }, 26 + "engines": { 27 + "node": ">=18.0.0" 28 + } 29 + }, 30 + "node_modules/@cloudflare/unenv-preset": { 31 + "version": "2.6.3", 32 + "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.6.3.tgz", 33 + "integrity": "sha512-Bj3i0kHAKFh/fViM8RT5ToV7w5Q8bGUR6yw4R0pkNktn559rmBMNf0+hkRmX8BmVH4WTo1Ye79zjkCxnmNt4+g==", 34 + "license": "MIT OR Apache-2.0", 35 + "peerDependencies": { 36 + "unenv": "2.0.0-rc.19", 37 + "workerd": "^1.20250802.0" 38 + }, 39 + "peerDependenciesMeta": { 40 + "workerd": { 41 + "optional": true 42 + } 43 + } 44 + }, 45 + "node_modules/@cloudflare/workerd-darwin-64": { 46 + "version": "1.20250823.0", 47 + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20250823.0.tgz", 48 + "integrity": "sha512-yRLJc1cQNqQYcDViOk7kpTXnR5XuBP7B/Ms5KBdlQ6eTr2Vsg9mfKqWKInjzY8/Cx+p+Sic2Tbld42gcYkiM2A==", 49 + "cpu": [ 50 + "x64" 51 + ], 52 + "license": "Apache-2.0", 53 + "optional": true, 54 + "os": [ 55 + "darwin" 56 + ], 57 + "engines": { 58 + "node": ">=16" 59 + } 60 + }, 61 + "node_modules/@cloudflare/workerd-darwin-arm64": { 62 + "version": "1.20250823.0", 63 + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20250823.0.tgz", 64 + "integrity": "sha512-KJnikUe6J29Ga1QMPKNCc8eHD56DdBlu5XE5LoBH/AYRrbS5UI1d5F844hUWoFKJb8KRaPIH9F849HZWfNa1vw==", 65 + "cpu": [ 66 + "arm64" 67 + ], 68 + "license": "Apache-2.0", 69 + "optional": true, 70 + "os": [ 71 + "darwin" 72 + ], 73 + "engines": { 74 + "node": ">=16" 75 + } 76 + }, 77 + "node_modules/@cloudflare/workerd-linux-64": { 78 + "version": "1.20250823.0", 79 + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20250823.0.tgz", 80 + "integrity": "sha512-4QFXq4eDWEAK5QjGxRe0XUTBax1Fgarc08HETL6q0y/KPZp2nOTLfjLjklTn/qEiztafNFoJEIwhkiknHeOi/g==", 81 + "cpu": [ 82 + "x64" 83 + ], 84 + "license": "Apache-2.0", 85 + "optional": true, 86 + "os": [ 87 + "linux" 88 + ], 89 + "engines": { 90 + "node": ">=16" 91 + } 92 + }, 93 + "node_modules/@cloudflare/workerd-linux-arm64": { 94 + "version": "1.20250823.0", 95 + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20250823.0.tgz", 96 + "integrity": "sha512-sODSrSVe4W/maoBu76qb0sJGBhxhSM2Q2tg/+G7q1IPgRZSzArMKIPrW6nBnmBrrG1O0X6aoAdID6w5hfuEM4g==", 97 + "cpu": [ 98 + "arm64" 99 + ], 100 + "license": "Apache-2.0", 101 + "optional": true, 102 + "os": [ 103 + "linux" 104 + ], 105 + "engines": { 106 + "node": ">=16" 107 + } 108 + }, 109 + "node_modules/@cloudflare/workerd-windows-64": { 110 + "version": "1.20250823.0", 111 + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20250823.0.tgz", 112 + "integrity": "sha512-WaNqUOXUnrcEI+i2NI4+okA9CrJMI9n2XTfVtDg/pLvcA/ZPTz23MEFMZU1splr4SslS1th1NBO38RMPnDB4rA==", 113 + "cpu": [ 114 + "x64" 115 + ], 116 + "license": "Apache-2.0", 117 + "optional": true, 118 + "os": [ 119 + "win32" 120 + ], 121 + "engines": { 122 + "node": ">=16" 123 + } 124 + }, 125 + "node_modules/@cspotcode/source-map-support": { 126 + "version": "0.8.1", 127 + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", 128 + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", 129 + "license": "MIT", 130 + "dependencies": { 131 + "@jridgewell/trace-mapping": "0.3.9" 132 + }, 133 + "engines": { 134 + "node": ">=12" 135 + } 136 + }, 137 + "node_modules/@emnapi/runtime": { 138 + "version": "1.4.5", 139 + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz", 140 + "integrity": "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==", 141 + "license": "MIT", 142 + "optional": true, 143 + "dependencies": { 144 + "tslib": "^2.4.0" 145 + } 146 + }, 147 + "node_modules/@esbuild/aix-ppc64": { 148 + "version": "0.25.4", 149 + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", 150 + "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", 151 + "cpu": [ 152 + "ppc64" 153 + ], 154 + "license": "MIT", 155 + "optional": true, 156 + "os": [ 157 + "aix" 158 + ], 159 + "engines": { 160 + "node": ">=18" 161 + } 162 + }, 163 + "node_modules/@esbuild/android-arm": { 164 + "version": "0.25.4", 165 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", 166 + "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", 167 + "cpu": [ 168 + "arm" 169 + ], 170 + "license": "MIT", 171 + "optional": true, 172 + "os": [ 173 + "android" 174 + ], 175 + "engines": { 176 + "node": ">=18" 177 + } 178 + }, 179 + "node_modules/@esbuild/android-arm64": { 180 + "version": "0.25.4", 181 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", 182 + "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", 183 + "cpu": [ 184 + "arm64" 185 + ], 186 + "license": "MIT", 187 + "optional": true, 188 + "os": [ 189 + "android" 190 + ], 191 + "engines": { 192 + "node": ">=18" 193 + } 194 + }, 195 + "node_modules/@esbuild/android-x64": { 196 + "version": "0.25.4", 197 + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz", 198 + "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", 199 + "cpu": [ 200 + "x64" 201 + ], 202 + "license": "MIT", 203 + "optional": true, 204 + "os": [ 205 + "android" 206 + ], 207 + "engines": { 208 + "node": ">=18" 209 + } 210 + }, 211 + "node_modules/@esbuild/darwin-arm64": { 212 + "version": "0.25.4", 213 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", 214 + "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", 215 + "cpu": [ 216 + "arm64" 217 + ], 218 + "license": "MIT", 219 + "optional": true, 220 + "os": [ 221 + "darwin" 222 + ], 223 + "engines": { 224 + "node": ">=18" 225 + } 226 + }, 227 + "node_modules/@esbuild/darwin-x64": { 228 + "version": "0.25.4", 229 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz", 230 + "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", 231 + "cpu": [ 232 + "x64" 233 + ], 234 + "license": "MIT", 235 + "optional": true, 236 + "os": [ 237 + "darwin" 238 + ], 239 + "engines": { 240 + "node": ">=18" 241 + } 242 + }, 243 + "node_modules/@esbuild/freebsd-arm64": { 244 + "version": "0.25.4", 245 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz", 246 + "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", 247 + "cpu": [ 248 + "arm64" 249 + ], 250 + "license": "MIT", 251 + "optional": true, 252 + "os": [ 253 + "freebsd" 254 + ], 255 + "engines": { 256 + "node": ">=18" 257 + } 258 + }, 259 + "node_modules/@esbuild/freebsd-x64": { 260 + "version": "0.25.4", 261 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz", 262 + "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", 263 + "cpu": [ 264 + "x64" 265 + ], 266 + "license": "MIT", 267 + "optional": true, 268 + "os": [ 269 + "freebsd" 270 + ], 271 + "engines": { 272 + "node": ">=18" 273 + } 274 + }, 275 + "node_modules/@esbuild/linux-arm": { 276 + "version": "0.25.4", 277 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz", 278 + "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", 279 + "cpu": [ 280 + "arm" 281 + ], 282 + "license": "MIT", 283 + "optional": true, 284 + "os": [ 285 + "linux" 286 + ], 287 + "engines": { 288 + "node": ">=18" 289 + } 290 + }, 291 + "node_modules/@esbuild/linux-arm64": { 292 + "version": "0.25.4", 293 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz", 294 + "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", 295 + "cpu": [ 296 + "arm64" 297 + ], 298 + "license": "MIT", 299 + "optional": true, 300 + "os": [ 301 + "linux" 302 + ], 303 + "engines": { 304 + "node": ">=18" 305 + } 306 + }, 307 + "node_modules/@esbuild/linux-ia32": { 308 + "version": "0.25.4", 309 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz", 310 + "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", 311 + "cpu": [ 312 + "ia32" 313 + ], 314 + "license": "MIT", 315 + "optional": true, 316 + "os": [ 317 + "linux" 318 + ], 319 + "engines": { 320 + "node": ">=18" 321 + } 322 + }, 323 + "node_modules/@esbuild/linux-loong64": { 324 + "version": "0.25.4", 325 + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz", 326 + "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", 327 + "cpu": [ 328 + "loong64" 329 + ], 330 + "license": "MIT", 331 + "optional": true, 332 + "os": [ 333 + "linux" 334 + ], 335 + "engines": { 336 + "node": ">=18" 337 + } 338 + }, 339 + "node_modules/@esbuild/linux-mips64el": { 340 + "version": "0.25.4", 341 + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz", 342 + "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", 343 + "cpu": [ 344 + "mips64el" 345 + ], 346 + "license": "MIT", 347 + "optional": true, 348 + "os": [ 349 + "linux" 350 + ], 351 + "engines": { 352 + "node": ">=18" 353 + } 354 + }, 355 + "node_modules/@esbuild/linux-ppc64": { 356 + "version": "0.25.4", 357 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz", 358 + "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", 359 + "cpu": [ 360 + "ppc64" 361 + ], 362 + "license": "MIT", 363 + "optional": true, 364 + "os": [ 365 + "linux" 366 + ], 367 + "engines": { 368 + "node": ">=18" 369 + } 370 + }, 371 + "node_modules/@esbuild/linux-riscv64": { 372 + "version": "0.25.4", 373 + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz", 374 + "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", 375 + "cpu": [ 376 + "riscv64" 377 + ], 378 + "license": "MIT", 379 + "optional": true, 380 + "os": [ 381 + "linux" 382 + ], 383 + "engines": { 384 + "node": ">=18" 385 + } 386 + }, 387 + "node_modules/@esbuild/linux-s390x": { 388 + "version": "0.25.4", 389 + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz", 390 + "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", 391 + "cpu": [ 392 + "s390x" 393 + ], 394 + "license": "MIT", 395 + "optional": true, 396 + "os": [ 397 + "linux" 398 + ], 399 + "engines": { 400 + "node": ">=18" 401 + } 402 + }, 403 + "node_modules/@esbuild/linux-x64": { 404 + "version": "0.25.4", 405 + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", 406 + "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", 407 + "cpu": [ 408 + "x64" 409 + ], 410 + "license": "MIT", 411 + "optional": true, 412 + "os": [ 413 + "linux" 414 + ], 415 + "engines": { 416 + "node": ">=18" 417 + } 418 + }, 419 + "node_modules/@esbuild/netbsd-arm64": { 420 + "version": "0.25.4", 421 + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz", 422 + "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", 423 + "cpu": [ 424 + "arm64" 425 + ], 426 + "license": "MIT", 427 + "optional": true, 428 + "os": [ 429 + "netbsd" 430 + ], 431 + "engines": { 432 + "node": ">=18" 433 + } 434 + }, 435 + "node_modules/@esbuild/netbsd-x64": { 436 + "version": "0.25.4", 437 + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz", 438 + "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", 439 + "cpu": [ 440 + "x64" 441 + ], 442 + "license": "MIT", 443 + "optional": true, 444 + "os": [ 445 + "netbsd" 446 + ], 447 + "engines": { 448 + "node": ">=18" 449 + } 450 + }, 451 + "node_modules/@esbuild/openbsd-arm64": { 452 + "version": "0.25.4", 453 + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz", 454 + "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", 455 + "cpu": [ 456 + "arm64" 457 + ], 458 + "license": "MIT", 459 + "optional": true, 460 + "os": [ 461 + "openbsd" 462 + ], 463 + "engines": { 464 + "node": ">=18" 465 + } 466 + }, 467 + "node_modules/@esbuild/openbsd-x64": { 468 + "version": "0.25.4", 469 + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz", 470 + "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", 471 + "cpu": [ 472 + "x64" 473 + ], 474 + "license": "MIT", 475 + "optional": true, 476 + "os": [ 477 + "openbsd" 478 + ], 479 + "engines": { 480 + "node": ">=18" 481 + } 482 + }, 483 + "node_modules/@esbuild/sunos-x64": { 484 + "version": "0.25.4", 485 + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz", 486 + "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", 487 + "cpu": [ 488 + "x64" 489 + ], 490 + "license": "MIT", 491 + "optional": true, 492 + "os": [ 493 + "sunos" 494 + ], 495 + "engines": { 496 + "node": ">=18" 497 + } 498 + }, 499 + "node_modules/@esbuild/win32-arm64": { 500 + "version": "0.25.4", 501 + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz", 502 + "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", 503 + "cpu": [ 504 + "arm64" 505 + ], 506 + "license": "MIT", 507 + "optional": true, 508 + "os": [ 509 + "win32" 510 + ], 511 + "engines": { 512 + "node": ">=18" 513 + } 514 + }, 515 + "node_modules/@esbuild/win32-ia32": { 516 + "version": "0.25.4", 517 + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz", 518 + "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", 519 + "cpu": [ 520 + "ia32" 521 + ], 522 + "license": "MIT", 523 + "optional": true, 524 + "os": [ 525 + "win32" 526 + ], 527 + "engines": { 528 + "node": ">=18" 529 + } 530 + }, 531 + "node_modules/@esbuild/win32-x64": { 532 + "version": "0.25.4", 533 + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz", 534 + "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", 535 + "cpu": [ 536 + "x64" 537 + ], 538 + "license": "MIT", 539 + "optional": true, 540 + "os": [ 541 + "win32" 542 + ], 543 + "engines": { 544 + "node": ">=18" 545 + } 546 + }, 547 + "node_modules/@img/sharp-darwin-arm64": { 548 + "version": "0.33.5", 549 + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", 550 + "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", 551 + "cpu": [ 552 + "arm64" 553 + ], 554 + "license": "Apache-2.0", 555 + "optional": true, 556 + "os": [ 557 + "darwin" 558 + ], 559 + "engines": { 560 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 561 + }, 562 + "funding": { 563 + "url": "https://opencollective.com/libvips" 564 + }, 565 + "optionalDependencies": { 566 + "@img/sharp-libvips-darwin-arm64": "1.0.4" 567 + } 568 + }, 569 + "node_modules/@img/sharp-darwin-x64": { 570 + "version": "0.33.5", 571 + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", 572 + "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", 573 + "cpu": [ 574 + "x64" 575 + ], 576 + "license": "Apache-2.0", 577 + "optional": true, 578 + "os": [ 579 + "darwin" 580 + ], 581 + "engines": { 582 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 583 + }, 584 + "funding": { 585 + "url": "https://opencollective.com/libvips" 586 + }, 587 + "optionalDependencies": { 588 + "@img/sharp-libvips-darwin-x64": "1.0.4" 589 + } 590 + }, 591 + "node_modules/@img/sharp-libvips-darwin-arm64": { 592 + "version": "1.0.4", 593 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", 594 + "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", 595 + "cpu": [ 596 + "arm64" 597 + ], 598 + "license": "LGPL-3.0-or-later", 599 + "optional": true, 600 + "os": [ 601 + "darwin" 602 + ], 603 + "funding": { 604 + "url": "https://opencollective.com/libvips" 605 + } 606 + }, 607 + "node_modules/@img/sharp-libvips-darwin-x64": { 608 + "version": "1.0.4", 609 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", 610 + "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", 611 + "cpu": [ 612 + "x64" 613 + ], 614 + "license": "LGPL-3.0-or-later", 615 + "optional": true, 616 + "os": [ 617 + "darwin" 618 + ], 619 + "funding": { 620 + "url": "https://opencollective.com/libvips" 621 + } 622 + }, 623 + "node_modules/@img/sharp-libvips-linux-arm": { 624 + "version": "1.0.5", 625 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", 626 + "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", 627 + "cpu": [ 628 + "arm" 629 + ], 630 + "license": "LGPL-3.0-or-later", 631 + "optional": true, 632 + "os": [ 633 + "linux" 634 + ], 635 + "funding": { 636 + "url": "https://opencollective.com/libvips" 637 + } 638 + }, 639 + "node_modules/@img/sharp-libvips-linux-arm64": { 640 + "version": "1.0.4", 641 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", 642 + "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", 643 + "cpu": [ 644 + "arm64" 645 + ], 646 + "license": "LGPL-3.0-or-later", 647 + "optional": true, 648 + "os": [ 649 + "linux" 650 + ], 651 + "funding": { 652 + "url": "https://opencollective.com/libvips" 653 + } 654 + }, 655 + "node_modules/@img/sharp-libvips-linux-s390x": { 656 + "version": "1.0.4", 657 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", 658 + "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", 659 + "cpu": [ 660 + "s390x" 661 + ], 662 + "license": "LGPL-3.0-or-later", 663 + "optional": true, 664 + "os": [ 665 + "linux" 666 + ], 667 + "funding": { 668 + "url": "https://opencollective.com/libvips" 669 + } 670 + }, 671 + "node_modules/@img/sharp-libvips-linux-x64": { 672 + "version": "1.0.4", 673 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", 674 + "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", 675 + "cpu": [ 676 + "x64" 677 + ], 678 + "license": "LGPL-3.0-or-later", 679 + "optional": true, 680 + "os": [ 681 + "linux" 682 + ], 683 + "funding": { 684 + "url": "https://opencollective.com/libvips" 685 + } 686 + }, 687 + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { 688 + "version": "1.0.4", 689 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", 690 + "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", 691 + "cpu": [ 692 + "arm64" 693 + ], 694 + "license": "LGPL-3.0-or-later", 695 + "optional": true, 696 + "os": [ 697 + "linux" 698 + ], 699 + "funding": { 700 + "url": "https://opencollective.com/libvips" 701 + } 702 + }, 703 + "node_modules/@img/sharp-libvips-linuxmusl-x64": { 704 + "version": "1.0.4", 705 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", 706 + "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", 707 + "cpu": [ 708 + "x64" 709 + ], 710 + "license": "LGPL-3.0-or-later", 711 + "optional": true, 712 + "os": [ 713 + "linux" 714 + ], 715 + "funding": { 716 + "url": "https://opencollective.com/libvips" 717 + } 718 + }, 719 + "node_modules/@img/sharp-linux-arm": { 720 + "version": "0.33.5", 721 + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", 722 + "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", 723 + "cpu": [ 724 + "arm" 725 + ], 726 + "license": "Apache-2.0", 727 + "optional": true, 728 + "os": [ 729 + "linux" 730 + ], 731 + "engines": { 732 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 733 + }, 734 + "funding": { 735 + "url": "https://opencollective.com/libvips" 736 + }, 737 + "optionalDependencies": { 738 + "@img/sharp-libvips-linux-arm": "1.0.5" 739 + } 740 + }, 741 + "node_modules/@img/sharp-linux-arm64": { 742 + "version": "0.33.5", 743 + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", 744 + "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", 745 + "cpu": [ 746 + "arm64" 747 + ], 748 + "license": "Apache-2.0", 749 + "optional": true, 750 + "os": [ 751 + "linux" 752 + ], 753 + "engines": { 754 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 755 + }, 756 + "funding": { 757 + "url": "https://opencollective.com/libvips" 758 + }, 759 + "optionalDependencies": { 760 + "@img/sharp-libvips-linux-arm64": "1.0.4" 761 + } 762 + }, 763 + "node_modules/@img/sharp-linux-s390x": { 764 + "version": "0.33.5", 765 + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", 766 + "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", 767 + "cpu": [ 768 + "s390x" 769 + ], 770 + "license": "Apache-2.0", 771 + "optional": true, 772 + "os": [ 773 + "linux" 774 + ], 775 + "engines": { 776 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 777 + }, 778 + "funding": { 779 + "url": "https://opencollective.com/libvips" 780 + }, 781 + "optionalDependencies": { 782 + "@img/sharp-libvips-linux-s390x": "1.0.4" 783 + } 784 + }, 785 + "node_modules/@img/sharp-linux-x64": { 786 + "version": "0.33.5", 787 + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", 788 + "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", 789 + "cpu": [ 790 + "x64" 791 + ], 792 + "license": "Apache-2.0", 793 + "optional": true, 794 + "os": [ 795 + "linux" 796 + ], 797 + "engines": { 798 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 799 + }, 800 + "funding": { 801 + "url": "https://opencollective.com/libvips" 802 + }, 803 + "optionalDependencies": { 804 + "@img/sharp-libvips-linux-x64": "1.0.4" 805 + } 806 + }, 807 + "node_modules/@img/sharp-linuxmusl-arm64": { 808 + "version": "0.33.5", 809 + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", 810 + "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", 811 + "cpu": [ 812 + "arm64" 813 + ], 814 + "license": "Apache-2.0", 815 + "optional": true, 816 + "os": [ 817 + "linux" 818 + ], 819 + "engines": { 820 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 821 + }, 822 + "funding": { 823 + "url": "https://opencollective.com/libvips" 824 + }, 825 + "optionalDependencies": { 826 + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" 827 + } 828 + }, 829 + "node_modules/@img/sharp-linuxmusl-x64": { 830 + "version": "0.33.5", 831 + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", 832 + "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", 833 + "cpu": [ 834 + "x64" 835 + ], 836 + "license": "Apache-2.0", 837 + "optional": true, 838 + "os": [ 839 + "linux" 840 + ], 841 + "engines": { 842 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 843 + }, 844 + "funding": { 845 + "url": "https://opencollective.com/libvips" 846 + }, 847 + "optionalDependencies": { 848 + "@img/sharp-libvips-linuxmusl-x64": "1.0.4" 849 + } 850 + }, 851 + "node_modules/@img/sharp-wasm32": { 852 + "version": "0.33.5", 853 + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", 854 + "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", 855 + "cpu": [ 856 + "wasm32" 857 + ], 858 + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", 859 + "optional": true, 860 + "dependencies": { 861 + "@emnapi/runtime": "^1.2.0" 862 + }, 863 + "engines": { 864 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 865 + }, 866 + "funding": { 867 + "url": "https://opencollective.com/libvips" 868 + } 869 + }, 870 + "node_modules/@img/sharp-win32-ia32": { 871 + "version": "0.33.5", 872 + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", 873 + "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", 874 + "cpu": [ 875 + "ia32" 876 + ], 877 + "license": "Apache-2.0 AND LGPL-3.0-or-later", 878 + "optional": true, 879 + "os": [ 880 + "win32" 881 + ], 882 + "engines": { 883 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 884 + }, 885 + "funding": { 886 + "url": "https://opencollective.com/libvips" 887 + } 888 + }, 889 + "node_modules/@img/sharp-win32-x64": { 890 + "version": "0.33.5", 891 + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", 892 + "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", 893 + "cpu": [ 894 + "x64" 895 + ], 896 + "license": "Apache-2.0 AND LGPL-3.0-or-later", 897 + "optional": true, 898 + "os": [ 899 + "win32" 900 + ], 901 + "engines": { 902 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 903 + }, 904 + "funding": { 905 + "url": "https://opencollective.com/libvips" 906 + } 907 + }, 908 + "node_modules/@jridgewell/resolve-uri": { 909 + "version": "3.1.2", 910 + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 911 + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 912 + "license": "MIT", 913 + "engines": { 914 + "node": ">=6.0.0" 915 + } 916 + }, 917 + "node_modules/@jridgewell/sourcemap-codec": { 918 + "version": "1.5.5", 919 + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", 920 + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", 921 + "license": "MIT" 922 + }, 923 + "node_modules/@jridgewell/trace-mapping": { 924 + "version": "0.3.9", 925 + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", 926 + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", 927 + "license": "MIT", 928 + "dependencies": { 929 + "@jridgewell/resolve-uri": "^3.0.3", 930 + "@jridgewell/sourcemap-codec": "^1.4.10" 931 + } 932 + }, 933 + "node_modules/@poppinss/colors": { 934 + "version": "4.1.5", 935 + "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.5.tgz", 936 + "integrity": "sha512-FvdDqtcRCtz6hThExcFOgW0cWX+xwSMWcRuQe5ZEb2m7cVQOAVZOIMt+/v9RxGiD9/OY16qJBXK4CVKWAPalBw==", 937 + "license": "MIT", 938 + "dependencies": { 939 + "kleur": "^4.1.5" 940 + } 941 + }, 942 + "node_modules/@poppinss/dumper": { 943 + "version": "0.6.4", 944 + "resolved": "https://registry.npmjs.org/@poppinss/dumper/-/dumper-0.6.4.tgz", 945 + "integrity": "sha512-iG0TIdqv8xJ3Lt9O8DrPRxw1MRLjNpoqiSGU03P/wNLP/s0ra0udPJ1J2Tx5M0J3H/cVyEgpbn8xUKRY9j59kQ==", 946 + "license": "MIT", 947 + "dependencies": { 948 + "@poppinss/colors": "^4.1.5", 949 + "@sindresorhus/is": "^7.0.2", 950 + "supports-color": "^10.0.0" 951 + } 952 + }, 953 + "node_modules/@poppinss/dumper/node_modules/supports-color": { 954 + "version": "10.2.0", 955 + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.0.tgz", 956 + "integrity": "sha512-5eG9FQjEjDbAlI5+kdpdyPIBMRH4GfTVDGREVupaZHmVoppknhM29b/S9BkQz7cathp85BVgRi/As3Siln7e0Q==", 957 + "license": "MIT", 958 + "engines": { 959 + "node": ">=18" 960 + }, 961 + "funding": { 962 + "url": "https://github.com/chalk/supports-color?sponsor=1" 963 + } 964 + }, 965 + "node_modules/@poppinss/exception": { 966 + "version": "1.2.2", 967 + "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.2.tgz", 968 + "integrity": "sha512-m7bpKCD4QMlFCjA/nKTs23fuvoVFoA83brRKmObCUNmi/9tVu8Ve3w4YQAnJu4q3Tjf5fr685HYIC/IA2zHRSg==", 969 + "license": "MIT" 970 + }, 971 + "node_modules/@sindresorhus/is": { 972 + "version": "7.0.2", 973 + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.0.2.tgz", 974 + "integrity": "sha512-d9xRovfKNz1SKieM0qJdO+PQonjnnIfSNWfHYnBSJ9hkjm0ZPw6HlxscDXYstp3z+7V2GOFHc+J0CYrYTjqCJw==", 975 + "license": "MIT", 976 + "engines": { 977 + "node": ">=18" 978 + }, 979 + "funding": { 980 + "url": "https://github.com/sindresorhus/is?sponsor=1" 981 + } 982 + }, 983 + "node_modules/@speed-highlight/core": { 984 + "version": "1.2.7", 985 + "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.7.tgz", 986 + "integrity": "sha512-0dxmVj4gxg3Jg879kvFS/msl4s9F3T9UXC1InxgOf7t5NvcPD97u/WTA5vL/IxWHMn7qSxBozqrnnE2wvl1m8g==", 987 + "license": "CC0-1.0" 988 + }, 989 + "node_modules/accepts": { 990 + "version": "2.0.0", 991 + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", 992 + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", 993 + "dependencies": { 994 + "mime-types": "^3.0.0", 995 + "negotiator": "^1.0.0" 996 + }, 997 + "engines": { 998 + "node": ">= 0.6" 999 + } 1000 + }, 1001 + "node_modules/acorn": { 1002 + "version": "8.14.0", 1003 + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", 1004 + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", 1005 + "license": "MIT", 1006 + "bin": { 1007 + "acorn": "bin/acorn" 1008 + }, 1009 + "engines": { 1010 + "node": ">=0.4.0" 1011 + } 1012 + }, 1013 + "node_modules/acorn-walk": { 1014 + "version": "8.3.2", 1015 + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", 1016 + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", 1017 + "license": "MIT", 1018 + "engines": { 1019 + "node": ">=0.4.0" 1020 + } 1021 + }, 1022 + "node_modules/anymatch": { 1023 + "version": "3.1.3", 1024 + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 1025 + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 1026 + "license": "ISC", 1027 + "dependencies": { 1028 + "normalize-path": "^3.0.0", 1029 + "picomatch": "^2.0.4" 1030 + }, 1031 + "engines": { 1032 + "node": ">= 8" 1033 + } 1034 + }, 1035 + "node_modules/balanced-match": { 1036 + "version": "1.0.2", 1037 + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 1038 + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 1039 + "license": "MIT" 1040 + }, 1041 + "node_modules/binary-extensions": { 1042 + "version": "2.3.0", 1043 + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", 1044 + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", 1045 + "license": "MIT", 1046 + "engines": { 1047 + "node": ">=8" 1048 + }, 1049 + "funding": { 1050 + "url": "https://github.com/sponsors/sindresorhus" 1051 + } 1052 + }, 1053 + "node_modules/blake3-wasm": { 1054 + "version": "2.1.5", 1055 + "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", 1056 + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", 1057 + "license": "MIT" 1058 + }, 1059 + "node_modules/body-parser": { 1060 + "version": "2.2.0", 1061 + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", 1062 + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", 1063 + "dependencies": { 1064 + "bytes": "^3.1.2", 1065 + "content-type": "^1.0.5", 1066 + "debug": "^4.4.0", 1067 + "http-errors": "^2.0.0", 1068 + "iconv-lite": "^0.6.3", 1069 + "on-finished": "^2.4.1", 1070 + "qs": "^6.14.0", 1071 + "raw-body": "^3.0.0", 1072 + "type-is": "^2.0.0" 1073 + }, 1074 + "engines": { 1075 + "node": ">=18" 1076 + } 1077 + }, 1078 + "node_modules/brace-expansion": { 1079 + "version": "1.1.12", 1080 + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", 1081 + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", 1082 + "license": "MIT", 1083 + "dependencies": { 1084 + "balanced-match": "^1.0.0", 1085 + "concat-map": "0.0.1" 1086 + } 1087 + }, 1088 + "node_modules/braces": { 1089 + "version": "3.0.3", 1090 + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", 1091 + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", 1092 + "license": "MIT", 1093 + "dependencies": { 1094 + "fill-range": "^7.1.1" 1095 + }, 1096 + "engines": { 1097 + "node": ">=8" 1098 + } 1099 + }, 1100 + "node_modules/bytes": { 1101 + "version": "3.1.2", 1102 + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 1103 + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 1104 + "engines": { 1105 + "node": ">= 0.8" 1106 + } 1107 + }, 1108 + "node_modules/call-bind-apply-helpers": { 1109 + "version": "1.0.2", 1110 + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", 1111 + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", 1112 + "dependencies": { 1113 + "es-errors": "^1.3.0", 1114 + "function-bind": "^1.1.2" 1115 + }, 1116 + "engines": { 1117 + "node": ">= 0.4" 1118 + } 1119 + }, 1120 + "node_modules/call-bound": { 1121 + "version": "1.0.4", 1122 + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", 1123 + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", 1124 + "dependencies": { 1125 + "call-bind-apply-helpers": "^1.0.2", 1126 + "get-intrinsic": "^1.3.0" 1127 + }, 1128 + "engines": { 1129 + "node": ">= 0.4" 1130 + }, 1131 + "funding": { 1132 + "url": "https://github.com/sponsors/ljharb" 1133 + } 1134 + }, 1135 + "node_modules/chokidar": { 1136 + "version": "3.6.0", 1137 + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", 1138 + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", 1139 + "license": "MIT", 1140 + "dependencies": { 1141 + "anymatch": "~3.1.2", 1142 + "braces": "~3.0.2", 1143 + "glob-parent": "~5.1.2", 1144 + "is-binary-path": "~2.1.0", 1145 + "is-glob": "~4.0.1", 1146 + "normalize-path": "~3.0.0", 1147 + "readdirp": "~3.6.0" 1148 + }, 1149 + "engines": { 1150 + "node": ">= 8.10.0" 1151 + }, 1152 + "funding": { 1153 + "url": "https://paulmillr.com/funding/" 1154 + }, 1155 + "optionalDependencies": { 1156 + "fsevents": "~2.3.2" 1157 + } 1158 + }, 1159 + "node_modules/color": { 1160 + "version": "4.2.3", 1161 + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", 1162 + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", 1163 + "license": "MIT", 1164 + "dependencies": { 1165 + "color-convert": "^2.0.1", 1166 + "color-string": "^1.9.0" 1167 + }, 1168 + "engines": { 1169 + "node": ">=12.5.0" 1170 + } 1171 + }, 1172 + "node_modules/color-convert": { 1173 + "version": "2.0.1", 1174 + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1175 + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1176 + "license": "MIT", 1177 + "dependencies": { 1178 + "color-name": "~1.1.4" 1179 + }, 1180 + "engines": { 1181 + "node": ">=7.0.0" 1182 + } 1183 + }, 1184 + "node_modules/color-name": { 1185 + "version": "1.1.4", 1186 + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1187 + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 1188 + "license": "MIT" 1189 + }, 1190 + "node_modules/color-string": { 1191 + "version": "1.9.1", 1192 + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", 1193 + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", 1194 + "license": "MIT", 1195 + "dependencies": { 1196 + "color-name": "^1.0.0", 1197 + "simple-swizzle": "^0.2.2" 1198 + } 1199 + }, 1200 + "node_modules/concat-map": { 1201 + "version": "0.0.1", 1202 + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 1203 + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 1204 + "license": "MIT" 1205 + }, 1206 + "node_modules/content-disposition": { 1207 + "version": "1.0.0", 1208 + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", 1209 + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", 1210 + "dependencies": { 1211 + "safe-buffer": "5.2.1" 1212 + }, 1213 + "engines": { 1214 + "node": ">= 0.6" 1215 + } 1216 + }, 1217 + "node_modules/content-type": { 1218 + "version": "1.0.5", 1219 + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 1220 + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 1221 + "engines": { 1222 + "node": ">= 0.6" 1223 + } 1224 + }, 1225 + "node_modules/cookie": { 1226 + "version": "0.7.2", 1227 + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", 1228 + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", 1229 + "engines": { 1230 + "node": ">= 0.6" 1231 + } 1232 + }, 1233 + "node_modules/cookie-signature": { 1234 + "version": "1.2.2", 1235 + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", 1236 + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", 1237 + "engines": { 1238 + "node": ">=6.6.0" 1239 + } 1240 + }, 1241 + "node_modules/debug": { 1242 + "version": "4.4.1", 1243 + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", 1244 + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", 1245 + "dependencies": { 1246 + "ms": "^2.1.3" 1247 + }, 1248 + "engines": { 1249 + "node": ">=6.0" 1250 + }, 1251 + "peerDependenciesMeta": { 1252 + "supports-color": { 1253 + "optional": true 1254 + } 1255 + } 1256 + }, 1257 + "node_modules/defu": { 1258 + "version": "6.1.4", 1259 + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", 1260 + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", 1261 + "license": "MIT" 1262 + }, 1263 + "node_modules/depd": { 1264 + "version": "2.0.0", 1265 + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 1266 + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 1267 + "engines": { 1268 + "node": ">= 0.8" 1269 + } 1270 + }, 1271 + "node_modules/detect-libc": { 1272 + "version": "2.0.4", 1273 + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", 1274 + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", 1275 + "license": "Apache-2.0", 1276 + "engines": { 1277 + "node": ">=8" 1278 + } 1279 + }, 1280 + "node_modules/dotenv": { 1281 + "version": "17.2.1", 1282 + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.1.tgz", 1283 + "integrity": "sha512-kQhDYKZecqnM0fCnzI5eIv5L4cAe/iRI+HqMbO/hbRdTAeXDG+M9FjipUxNfbARuEg4iHIbhnhs78BCHNbSxEQ==", 1284 + "license": "BSD-2-Clause", 1285 + "engines": { 1286 + "node": ">=12" 1287 + }, 1288 + "funding": { 1289 + "url": "https://dotenvx.com" 1290 + } 1291 + }, 1292 + "node_modules/dunder-proto": { 1293 + "version": "1.0.1", 1294 + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", 1295 + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", 1296 + "dependencies": { 1297 + "call-bind-apply-helpers": "^1.0.1", 1298 + "es-errors": "^1.3.0", 1299 + "gopd": "^1.2.0" 1300 + }, 1301 + "engines": { 1302 + "node": ">= 0.4" 1303 + } 1304 + }, 1305 + "node_modules/ee-first": { 1306 + "version": "1.1.1", 1307 + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 1308 + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 1309 + }, 1310 + "node_modules/encodeurl": { 1311 + "version": "2.0.0", 1312 + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 1313 + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", 1314 + "engines": { 1315 + "node": ">= 0.8" 1316 + } 1317 + }, 1318 + "node_modules/error-stack-parser-es": { 1319 + "version": "1.0.5", 1320 + "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", 1321 + "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", 1322 + "license": "MIT", 1323 + "funding": { 1324 + "url": "https://github.com/sponsors/antfu" 1325 + } 1326 + }, 1327 + "node_modules/es-define-property": { 1328 + "version": "1.0.1", 1329 + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", 1330 + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", 1331 + "engines": { 1332 + "node": ">= 0.4" 1333 + } 1334 + }, 1335 + "node_modules/es-errors": { 1336 + "version": "1.3.0", 1337 + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 1338 + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 1339 + "engines": { 1340 + "node": ">= 0.4" 1341 + } 1342 + }, 1343 + "node_modules/es-object-atoms": { 1344 + "version": "1.1.1", 1345 + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", 1346 + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", 1347 + "dependencies": { 1348 + "es-errors": "^1.3.0" 1349 + }, 1350 + "engines": { 1351 + "node": ">= 0.4" 1352 + } 1353 + }, 1354 + "node_modules/esbuild": { 1355 + "version": "0.25.4", 1356 + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", 1357 + "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", 1358 + "hasInstallScript": true, 1359 + "license": "MIT", 1360 + "bin": { 1361 + "esbuild": "bin/esbuild" 1362 + }, 1363 + "engines": { 1364 + "node": ">=18" 1365 + }, 1366 + "optionalDependencies": { 1367 + "@esbuild/aix-ppc64": "0.25.4", 1368 + "@esbuild/android-arm": "0.25.4", 1369 + "@esbuild/android-arm64": "0.25.4", 1370 + "@esbuild/android-x64": "0.25.4", 1371 + "@esbuild/darwin-arm64": "0.25.4", 1372 + "@esbuild/darwin-x64": "0.25.4", 1373 + "@esbuild/freebsd-arm64": "0.25.4", 1374 + "@esbuild/freebsd-x64": "0.25.4", 1375 + "@esbuild/linux-arm": "0.25.4", 1376 + "@esbuild/linux-arm64": "0.25.4", 1377 + "@esbuild/linux-ia32": "0.25.4", 1378 + "@esbuild/linux-loong64": "0.25.4", 1379 + "@esbuild/linux-mips64el": "0.25.4", 1380 + "@esbuild/linux-ppc64": "0.25.4", 1381 + "@esbuild/linux-riscv64": "0.25.4", 1382 + "@esbuild/linux-s390x": "0.25.4", 1383 + "@esbuild/linux-x64": "0.25.4", 1384 + "@esbuild/netbsd-arm64": "0.25.4", 1385 + "@esbuild/netbsd-x64": "0.25.4", 1386 + "@esbuild/openbsd-arm64": "0.25.4", 1387 + "@esbuild/openbsd-x64": "0.25.4", 1388 + "@esbuild/sunos-x64": "0.25.4", 1389 + "@esbuild/win32-arm64": "0.25.4", 1390 + "@esbuild/win32-ia32": "0.25.4", 1391 + "@esbuild/win32-x64": "0.25.4" 1392 + } 1393 + }, 1394 + "node_modules/escape-html": { 1395 + "version": "1.0.3", 1396 + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 1397 + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 1398 + }, 1399 + "node_modules/etag": { 1400 + "version": "1.8.1", 1401 + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 1402 + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 1403 + "engines": { 1404 + "node": ">= 0.6" 1405 + } 1406 + }, 1407 + "node_modules/exit-hook": { 1408 + "version": "2.2.1", 1409 + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", 1410 + "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", 1411 + "license": "MIT", 1412 + "engines": { 1413 + "node": ">=6" 1414 + }, 1415 + "funding": { 1416 + "url": "https://github.com/sponsors/sindresorhus" 1417 + } 1418 + }, 1419 + "node_modules/express": { 1420 + "version": "5.1.0", 1421 + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", 1422 + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", 1423 + "dependencies": { 1424 + "accepts": "^2.0.0", 1425 + "body-parser": "^2.2.0", 1426 + "content-disposition": "^1.0.0", 1427 + "content-type": "^1.0.5", 1428 + "cookie": "^0.7.1", 1429 + "cookie-signature": "^1.2.1", 1430 + "debug": "^4.4.0", 1431 + "encodeurl": "^2.0.0", 1432 + "escape-html": "^1.0.3", 1433 + "etag": "^1.8.1", 1434 + "finalhandler": "^2.1.0", 1435 + "fresh": "^2.0.0", 1436 + "http-errors": "^2.0.0", 1437 + "merge-descriptors": "^2.0.0", 1438 + "mime-types": "^3.0.0", 1439 + "on-finished": "^2.4.1", 1440 + "once": "^1.4.0", 1441 + "parseurl": "^1.3.3", 1442 + "proxy-addr": "^2.0.7", 1443 + "qs": "^6.14.0", 1444 + "range-parser": "^1.2.1", 1445 + "router": "^2.2.0", 1446 + "send": "^1.1.0", 1447 + "serve-static": "^2.2.0", 1448 + "statuses": "^2.0.1", 1449 + "type-is": "^2.0.1", 1450 + "vary": "^1.1.2" 1451 + }, 1452 + "engines": { 1453 + "node": ">= 18" 1454 + }, 1455 + "funding": { 1456 + "type": "opencollective", 1457 + "url": "https://opencollective.com/express" 1458 + } 1459 + }, 1460 + "node_modules/exsolve": { 1461 + "version": "1.0.7", 1462 + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", 1463 + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", 1464 + "license": "MIT" 1465 + }, 1466 + "node_modules/fill-range": { 1467 + "version": "7.1.1", 1468 + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", 1469 + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", 1470 + "license": "MIT", 1471 + "dependencies": { 1472 + "to-regex-range": "^5.0.1" 1473 + }, 1474 + "engines": { 1475 + "node": ">=8" 1476 + } 1477 + }, 1478 + "node_modules/finalhandler": { 1479 + "version": "2.1.0", 1480 + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", 1481 + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", 1482 + "dependencies": { 1483 + "debug": "^4.4.0", 1484 + "encodeurl": "^2.0.0", 1485 + "escape-html": "^1.0.3", 1486 + "on-finished": "^2.4.1", 1487 + "parseurl": "^1.3.3", 1488 + "statuses": "^2.0.1" 1489 + }, 1490 + "engines": { 1491 + "node": ">= 0.8" 1492 + } 1493 + }, 1494 + "node_modules/forwarded": { 1495 + "version": "0.2.0", 1496 + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 1497 + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 1498 + "engines": { 1499 + "node": ">= 0.6" 1500 + } 1501 + }, 1502 + "node_modules/fresh": { 1503 + "version": "2.0.0", 1504 + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", 1505 + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", 1506 + "engines": { 1507 + "node": ">= 0.8" 1508 + } 1509 + }, 1510 + "node_modules/fsevents": { 1511 + "version": "2.3.3", 1512 + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1513 + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1514 + "hasInstallScript": true, 1515 + "license": "MIT", 1516 + "optional": true, 1517 + "os": [ 1518 + "darwin" 1519 + ], 1520 + "engines": { 1521 + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1522 + } 1523 + }, 1524 + "node_modules/function-bind": { 1525 + "version": "1.1.2", 1526 + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 1527 + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 1528 + "funding": { 1529 + "url": "https://github.com/sponsors/ljharb" 1530 + } 1531 + }, 1532 + "node_modules/get-intrinsic": { 1533 + "version": "1.3.0", 1534 + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", 1535 + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", 1536 + "dependencies": { 1537 + "call-bind-apply-helpers": "^1.0.2", 1538 + "es-define-property": "^1.0.1", 1539 + "es-errors": "^1.3.0", 1540 + "es-object-atoms": "^1.1.1", 1541 + "function-bind": "^1.1.2", 1542 + "get-proto": "^1.0.1", 1543 + "gopd": "^1.2.0", 1544 + "has-symbols": "^1.1.0", 1545 + "hasown": "^2.0.2", 1546 + "math-intrinsics": "^1.1.0" 1547 + }, 1548 + "engines": { 1549 + "node": ">= 0.4" 1550 + }, 1551 + "funding": { 1552 + "url": "https://github.com/sponsors/ljharb" 1553 + } 1554 + }, 1555 + "node_modules/get-proto": { 1556 + "version": "1.0.1", 1557 + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", 1558 + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", 1559 + "dependencies": { 1560 + "dunder-proto": "^1.0.1", 1561 + "es-object-atoms": "^1.0.0" 1562 + }, 1563 + "engines": { 1564 + "node": ">= 0.4" 1565 + } 1566 + }, 1567 + "node_modules/glob-parent": { 1568 + "version": "5.1.2", 1569 + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 1570 + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 1571 + "license": "ISC", 1572 + "dependencies": { 1573 + "is-glob": "^4.0.1" 1574 + }, 1575 + "engines": { 1576 + "node": ">= 6" 1577 + } 1578 + }, 1579 + "node_modules/glob-to-regexp": { 1580 + "version": "0.4.1", 1581 + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", 1582 + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", 1583 + "license": "BSD-2-Clause" 1584 + }, 1585 + "node_modules/gopd": { 1586 + "version": "1.2.0", 1587 + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", 1588 + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", 1589 + "engines": { 1590 + "node": ">= 0.4" 1591 + }, 1592 + "funding": { 1593 + "url": "https://github.com/sponsors/ljharb" 1594 + } 1595 + }, 1596 + "node_modules/has-flag": { 1597 + "version": "3.0.0", 1598 + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 1599 + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", 1600 + "license": "MIT", 1601 + "engines": { 1602 + "node": ">=4" 1603 + } 1604 + }, 1605 + "node_modules/has-symbols": { 1606 + "version": "1.1.0", 1607 + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", 1608 + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", 1609 + "engines": { 1610 + "node": ">= 0.4" 1611 + }, 1612 + "funding": { 1613 + "url": "https://github.com/sponsors/ljharb" 1614 + } 1615 + }, 1616 + "node_modules/hasown": { 1617 + "version": "2.0.2", 1618 + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 1619 + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 1620 + "dependencies": { 1621 + "function-bind": "^1.1.2" 1622 + }, 1623 + "engines": { 1624 + "node": ">= 0.4" 1625 + } 1626 + }, 1627 + "node_modules/http-errors": { 1628 + "version": "2.0.0", 1629 + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 1630 + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 1631 + "dependencies": { 1632 + "depd": "2.0.0", 1633 + "inherits": "2.0.4", 1634 + "setprototypeof": "1.2.0", 1635 + "statuses": "2.0.1", 1636 + "toidentifier": "1.0.1" 1637 + }, 1638 + "engines": { 1639 + "node": ">= 0.8" 1640 + } 1641 + }, 1642 + "node_modules/http-errors/node_modules/statuses": { 1643 + "version": "2.0.1", 1644 + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 1645 + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 1646 + "engines": { 1647 + "node": ">= 0.8" 1648 + } 1649 + }, 1650 + "node_modules/iconv-lite": { 1651 + "version": "0.6.3", 1652 + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 1653 + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 1654 + "dependencies": { 1655 + "safer-buffer": ">= 2.1.2 < 3.0.0" 1656 + }, 1657 + "engines": { 1658 + "node": ">=0.10.0" 1659 + } 1660 + }, 1661 + "node_modules/ignore-by-default": { 1662 + "version": "1.0.1", 1663 + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", 1664 + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", 1665 + "license": "ISC" 1666 + }, 1667 + "node_modules/inherits": { 1668 + "version": "2.0.4", 1669 + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1670 + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 1671 + }, 1672 + "node_modules/ipaddr.js": { 1673 + "version": "1.9.1", 1674 + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 1675 + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 1676 + "engines": { 1677 + "node": ">= 0.10" 1678 + } 1679 + }, 1680 + "node_modules/is-arrayish": { 1681 + "version": "0.3.2", 1682 + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", 1683 + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", 1684 + "license": "MIT" 1685 + }, 1686 + "node_modules/is-binary-path": { 1687 + "version": "2.1.0", 1688 + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 1689 + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 1690 + "license": "MIT", 1691 + "dependencies": { 1692 + "binary-extensions": "^2.0.0" 1693 + }, 1694 + "engines": { 1695 + "node": ">=8" 1696 + } 1697 + }, 1698 + "node_modules/is-extglob": { 1699 + "version": "2.1.1", 1700 + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1701 + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 1702 + "license": "MIT", 1703 + "engines": { 1704 + "node": ">=0.10.0" 1705 + } 1706 + }, 1707 + "node_modules/is-glob": { 1708 + "version": "4.0.3", 1709 + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 1710 + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 1711 + "license": "MIT", 1712 + "dependencies": { 1713 + "is-extglob": "^2.1.1" 1714 + }, 1715 + "engines": { 1716 + "node": ">=0.10.0" 1717 + } 1718 + }, 1719 + "node_modules/is-number": { 1720 + "version": "7.0.0", 1721 + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1722 + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1723 + "license": "MIT", 1724 + "engines": { 1725 + "node": ">=0.12.0" 1726 + } 1727 + }, 1728 + "node_modules/is-promise": { 1729 + "version": "4.0.0", 1730 + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", 1731 + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" 1732 + }, 1733 + "node_modules/kleur": { 1734 + "version": "4.1.5", 1735 + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", 1736 + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", 1737 + "license": "MIT", 1738 + "engines": { 1739 + "node": ">=6" 1740 + } 1741 + }, 1742 + "node_modules/math-intrinsics": { 1743 + "version": "1.1.0", 1744 + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", 1745 + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", 1746 + "engines": { 1747 + "node": ">= 0.4" 1748 + } 1749 + }, 1750 + "node_modules/media-typer": { 1751 + "version": "1.1.0", 1752 + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", 1753 + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", 1754 + "engines": { 1755 + "node": ">= 0.8" 1756 + } 1757 + }, 1758 + "node_modules/merge-descriptors": { 1759 + "version": "2.0.0", 1760 + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", 1761 + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", 1762 + "engines": { 1763 + "node": ">=18" 1764 + }, 1765 + "funding": { 1766 + "url": "https://github.com/sponsors/sindresorhus" 1767 + } 1768 + }, 1769 + "node_modules/mime": { 1770 + "version": "3.0.0", 1771 + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", 1772 + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", 1773 + "license": "MIT", 1774 + "bin": { 1775 + "mime": "cli.js" 1776 + }, 1777 + "engines": { 1778 + "node": ">=10.0.0" 1779 + } 1780 + }, 1781 + "node_modules/mime-db": { 1782 + "version": "1.54.0", 1783 + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", 1784 + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", 1785 + "engines": { 1786 + "node": ">= 0.6" 1787 + } 1788 + }, 1789 + "node_modules/mime-types": { 1790 + "version": "3.0.1", 1791 + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", 1792 + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", 1793 + "dependencies": { 1794 + "mime-db": "^1.54.0" 1795 + }, 1796 + "engines": { 1797 + "node": ">= 0.6" 1798 + } 1799 + }, 1800 + "node_modules/miniflare": { 1801 + "version": "4.20250823.0", 1802 + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20250823.0.tgz", 1803 + "integrity": "sha512-ofQRQ6rb/5P4nsz/J+xptdrN4zvYUm0wuezbKfaxbAGiIVTsM1vd+Pta5MtZwdQ6BKLM9tKMtU0rnbTzy3wntQ==", 1804 + "license": "MIT", 1805 + "dependencies": { 1806 + "@cspotcode/source-map-support": "0.8.1", 1807 + "acorn": "8.14.0", 1808 + "acorn-walk": "8.3.2", 1809 + "exit-hook": "2.2.1", 1810 + "glob-to-regexp": "0.4.1", 1811 + "sharp": "^0.33.5", 1812 + "stoppable": "1.1.0", 1813 + "undici": "^7.10.0", 1814 + "workerd": "1.20250823.0", 1815 + "ws": "8.18.0", 1816 + "youch": "4.1.0-beta.10", 1817 + "zod": "3.22.3" 1818 + }, 1819 + "bin": { 1820 + "miniflare": "bootstrap.js" 1821 + }, 1822 + "engines": { 1823 + "node": ">=18.0.0" 1824 + } 1825 + }, 1826 + "node_modules/minimatch": { 1827 + "version": "3.1.2", 1828 + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1829 + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1830 + "license": "ISC", 1831 + "dependencies": { 1832 + "brace-expansion": "^1.1.7" 1833 + }, 1834 + "engines": { 1835 + "node": "*" 1836 + } 1837 + }, 1838 + "node_modules/ms": { 1839 + "version": "2.1.3", 1840 + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1841 + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 1842 + }, 1843 + "node_modules/negotiator": { 1844 + "version": "1.0.0", 1845 + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", 1846 + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", 1847 + "engines": { 1848 + "node": ">= 0.6" 1849 + } 1850 + }, 1851 + "node_modules/nodemon": { 1852 + "version": "3.1.10", 1853 + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.10.tgz", 1854 + "integrity": "sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==", 1855 + "license": "MIT", 1856 + "dependencies": { 1857 + "chokidar": "^3.5.2", 1858 + "debug": "^4", 1859 + "ignore-by-default": "^1.0.1", 1860 + "minimatch": "^3.1.2", 1861 + "pstree.remy": "^1.1.8", 1862 + "semver": "^7.5.3", 1863 + "simple-update-notifier": "^2.0.0", 1864 + "supports-color": "^5.5.0", 1865 + "touch": "^3.1.0", 1866 + "undefsafe": "^2.0.5" 1867 + }, 1868 + "bin": { 1869 + "nodemon": "bin/nodemon.js" 1870 + }, 1871 + "engines": { 1872 + "node": ">=10" 1873 + }, 1874 + "funding": { 1875 + "type": "opencollective", 1876 + "url": "https://opencollective.com/nodemon" 1877 + } 1878 + }, 1879 + "node_modules/normalize-path": { 1880 + "version": "3.0.0", 1881 + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1882 + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1883 + "license": "MIT", 1884 + "engines": { 1885 + "node": ">=0.10.0" 1886 + } 1887 + }, 1888 + "node_modules/object-inspect": { 1889 + "version": "1.13.4", 1890 + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", 1891 + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", 1892 + "engines": { 1893 + "node": ">= 0.4" 1894 + }, 1895 + "funding": { 1896 + "url": "https://github.com/sponsors/ljharb" 1897 + } 1898 + }, 1899 + "node_modules/ohash": { 1900 + "version": "2.0.11", 1901 + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", 1902 + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", 1903 + "license": "MIT" 1904 + }, 1905 + "node_modules/on-finished": { 1906 + "version": "2.4.1", 1907 + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 1908 + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 1909 + "dependencies": { 1910 + "ee-first": "1.1.1" 1911 + }, 1912 + "engines": { 1913 + "node": ">= 0.8" 1914 + } 1915 + }, 1916 + "node_modules/once": { 1917 + "version": "1.4.0", 1918 + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1919 + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 1920 + "dependencies": { 1921 + "wrappy": "1" 1922 + } 1923 + }, 1924 + "node_modules/parseurl": { 1925 + "version": "1.3.3", 1926 + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1927 + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 1928 + "engines": { 1929 + "node": ">= 0.8" 1930 + } 1931 + }, 1932 + "node_modules/path-to-regexp": { 1933 + "version": "8.2.0", 1934 + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", 1935 + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", 1936 + "engines": { 1937 + "node": ">=16" 1938 + } 1939 + }, 1940 + "node_modules/pathe": { 1941 + "version": "2.0.3", 1942 + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", 1943 + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", 1944 + "license": "MIT" 1945 + }, 1946 + "node_modules/picomatch": { 1947 + "version": "2.3.1", 1948 + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1949 + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1950 + "license": "MIT", 1951 + "engines": { 1952 + "node": ">=8.6" 1953 + }, 1954 + "funding": { 1955 + "url": "https://github.com/sponsors/jonschlinkert" 1956 + } 1957 + }, 1958 + "node_modules/proxy-addr": { 1959 + "version": "2.0.7", 1960 + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 1961 + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 1962 + "dependencies": { 1963 + "forwarded": "0.2.0", 1964 + "ipaddr.js": "1.9.1" 1965 + }, 1966 + "engines": { 1967 + "node": ">= 0.10" 1968 + } 1969 + }, 1970 + "node_modules/pstree.remy": { 1971 + "version": "1.1.8", 1972 + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", 1973 + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", 1974 + "license": "MIT" 1975 + }, 1976 + "node_modules/qs": { 1977 + "version": "6.14.0", 1978 + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", 1979 + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", 1980 + "dependencies": { 1981 + "side-channel": "^1.1.0" 1982 + }, 1983 + "engines": { 1984 + "node": ">=0.6" 1985 + }, 1986 + "funding": { 1987 + "url": "https://github.com/sponsors/ljharb" 1988 + } 1989 + }, 1990 + "node_modules/range-parser": { 1991 + "version": "1.2.1", 1992 + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1993 + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 1994 + "engines": { 1995 + "node": ">= 0.6" 1996 + } 1997 + }, 1998 + "node_modules/raw-body": { 1999 + "version": "3.0.0", 2000 + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", 2001 + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", 2002 + "dependencies": { 2003 + "bytes": "3.1.2", 2004 + "http-errors": "2.0.0", 2005 + "iconv-lite": "0.6.3", 2006 + "unpipe": "1.0.0" 2007 + }, 2008 + "engines": { 2009 + "node": ">= 0.8" 2010 + } 2011 + }, 2012 + "node_modules/readdirp": { 2013 + "version": "3.6.0", 2014 + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 2015 + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 2016 + "license": "MIT", 2017 + "dependencies": { 2018 + "picomatch": "^2.2.1" 2019 + }, 2020 + "engines": { 2021 + "node": ">=8.10.0" 2022 + } 2023 + }, 2024 + "node_modules/router": { 2025 + "version": "2.2.0", 2026 + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", 2027 + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", 2028 + "dependencies": { 2029 + "debug": "^4.4.0", 2030 + "depd": "^2.0.0", 2031 + "is-promise": "^4.0.0", 2032 + "parseurl": "^1.3.3", 2033 + "path-to-regexp": "^8.0.0" 2034 + }, 2035 + "engines": { 2036 + "node": ">= 18" 2037 + } 2038 + }, 2039 + "node_modules/safe-buffer": { 2040 + "version": "5.2.1", 2041 + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 2042 + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 2043 + "funding": [ 2044 + { 2045 + "type": "github", 2046 + "url": "https://github.com/sponsors/feross" 2047 + }, 2048 + { 2049 + "type": "patreon", 2050 + "url": "https://www.patreon.com/feross" 2051 + }, 2052 + { 2053 + "type": "consulting", 2054 + "url": "https://feross.org/support" 2055 + } 2056 + ] 2057 + }, 2058 + "node_modules/safer-buffer": { 2059 + "version": "2.1.2", 2060 + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 2061 + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 2062 + }, 2063 + "node_modules/semver": { 2064 + "version": "7.7.2", 2065 + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", 2066 + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", 2067 + "license": "ISC", 2068 + "bin": { 2069 + "semver": "bin/semver.js" 2070 + }, 2071 + "engines": { 2072 + "node": ">=10" 2073 + } 2074 + }, 2075 + "node_modules/send": { 2076 + "version": "1.2.0", 2077 + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", 2078 + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", 2079 + "dependencies": { 2080 + "debug": "^4.3.5", 2081 + "encodeurl": "^2.0.0", 2082 + "escape-html": "^1.0.3", 2083 + "etag": "^1.8.1", 2084 + "fresh": "^2.0.0", 2085 + "http-errors": "^2.0.0", 2086 + "mime-types": "^3.0.1", 2087 + "ms": "^2.1.3", 2088 + "on-finished": "^2.4.1", 2089 + "range-parser": "^1.2.1", 2090 + "statuses": "^2.0.1" 2091 + }, 2092 + "engines": { 2093 + "node": ">= 18" 2094 + } 2095 + }, 2096 + "node_modules/serve-static": { 2097 + "version": "2.2.0", 2098 + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", 2099 + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", 2100 + "dependencies": { 2101 + "encodeurl": "^2.0.0", 2102 + "escape-html": "^1.0.3", 2103 + "parseurl": "^1.3.3", 2104 + "send": "^1.2.0" 2105 + }, 2106 + "engines": { 2107 + "node": ">= 18" 2108 + } 2109 + }, 2110 + "node_modules/setprototypeof": { 2111 + "version": "1.2.0", 2112 + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 2113 + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 2114 + }, 2115 + "node_modules/sharp": { 2116 + "version": "0.33.5", 2117 + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", 2118 + "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", 2119 + "hasInstallScript": true, 2120 + "license": "Apache-2.0", 2121 + "dependencies": { 2122 + "color": "^4.2.3", 2123 + "detect-libc": "^2.0.3", 2124 + "semver": "^7.6.3" 2125 + }, 2126 + "engines": { 2127 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 2128 + }, 2129 + "funding": { 2130 + "url": "https://opencollective.com/libvips" 2131 + }, 2132 + "optionalDependencies": { 2133 + "@img/sharp-darwin-arm64": "0.33.5", 2134 + "@img/sharp-darwin-x64": "0.33.5", 2135 + "@img/sharp-libvips-darwin-arm64": "1.0.4", 2136 + "@img/sharp-libvips-darwin-x64": "1.0.4", 2137 + "@img/sharp-libvips-linux-arm": "1.0.5", 2138 + "@img/sharp-libvips-linux-arm64": "1.0.4", 2139 + "@img/sharp-libvips-linux-s390x": "1.0.4", 2140 + "@img/sharp-libvips-linux-x64": "1.0.4", 2141 + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", 2142 + "@img/sharp-libvips-linuxmusl-x64": "1.0.4", 2143 + "@img/sharp-linux-arm": "0.33.5", 2144 + "@img/sharp-linux-arm64": "0.33.5", 2145 + "@img/sharp-linux-s390x": "0.33.5", 2146 + "@img/sharp-linux-x64": "0.33.5", 2147 + "@img/sharp-linuxmusl-arm64": "0.33.5", 2148 + "@img/sharp-linuxmusl-x64": "0.33.5", 2149 + "@img/sharp-wasm32": "0.33.5", 2150 + "@img/sharp-win32-ia32": "0.33.5", 2151 + "@img/sharp-win32-x64": "0.33.5" 2152 + } 2153 + }, 2154 + "node_modules/side-channel": { 2155 + "version": "1.1.0", 2156 + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", 2157 + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", 2158 + "dependencies": { 2159 + "es-errors": "^1.3.0", 2160 + "object-inspect": "^1.13.3", 2161 + "side-channel-list": "^1.0.0", 2162 + "side-channel-map": "^1.0.1", 2163 + "side-channel-weakmap": "^1.0.2" 2164 + }, 2165 + "engines": { 2166 + "node": ">= 0.4" 2167 + }, 2168 + "funding": { 2169 + "url": "https://github.com/sponsors/ljharb" 2170 + } 2171 + }, 2172 + "node_modules/side-channel-list": { 2173 + "version": "1.0.0", 2174 + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", 2175 + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", 2176 + "dependencies": { 2177 + "es-errors": "^1.3.0", 2178 + "object-inspect": "^1.13.3" 2179 + }, 2180 + "engines": { 2181 + "node": ">= 0.4" 2182 + }, 2183 + "funding": { 2184 + "url": "https://github.com/sponsors/ljharb" 2185 + } 2186 + }, 2187 + "node_modules/side-channel-map": { 2188 + "version": "1.0.1", 2189 + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", 2190 + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", 2191 + "dependencies": { 2192 + "call-bound": "^1.0.2", 2193 + "es-errors": "^1.3.0", 2194 + "get-intrinsic": "^1.2.5", 2195 + "object-inspect": "^1.13.3" 2196 + }, 2197 + "engines": { 2198 + "node": ">= 0.4" 2199 + }, 2200 + "funding": { 2201 + "url": "https://github.com/sponsors/ljharb" 2202 + } 2203 + }, 2204 + "node_modules/side-channel-weakmap": { 2205 + "version": "1.0.2", 2206 + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", 2207 + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", 2208 + "dependencies": { 2209 + "call-bound": "^1.0.2", 2210 + "es-errors": "^1.3.0", 2211 + "get-intrinsic": "^1.2.5", 2212 + "object-inspect": "^1.13.3", 2213 + "side-channel-map": "^1.0.1" 2214 + }, 2215 + "engines": { 2216 + "node": ">= 0.4" 2217 + }, 2218 + "funding": { 2219 + "url": "https://github.com/sponsors/ljharb" 2220 + } 2221 + }, 2222 + "node_modules/simple-swizzle": { 2223 + "version": "0.2.2", 2224 + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", 2225 + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", 2226 + "license": "MIT", 2227 + "dependencies": { 2228 + "is-arrayish": "^0.3.1" 2229 + } 2230 + }, 2231 + "node_modules/simple-update-notifier": { 2232 + "version": "2.0.0", 2233 + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", 2234 + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", 2235 + "license": "MIT", 2236 + "dependencies": { 2237 + "semver": "^7.5.3" 2238 + }, 2239 + "engines": { 2240 + "node": ">=10" 2241 + } 2242 + }, 2243 + "node_modules/statuses": { 2244 + "version": "2.0.2", 2245 + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", 2246 + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", 2247 + "engines": { 2248 + "node": ">= 0.8" 2249 + } 2250 + }, 2251 + "node_modules/stoppable": { 2252 + "version": "1.1.0", 2253 + "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", 2254 + "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", 2255 + "license": "MIT", 2256 + "engines": { 2257 + "node": ">=4", 2258 + "npm": ">=6" 2259 + } 2260 + }, 2261 + "node_modules/supports-color": { 2262 + "version": "5.5.0", 2263 + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 2264 + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 2265 + "license": "MIT", 2266 + "dependencies": { 2267 + "has-flag": "^3.0.0" 2268 + }, 2269 + "engines": { 2270 + "node": ">=4" 2271 + } 2272 + }, 2273 + "node_modules/to-regex-range": { 2274 + "version": "5.0.1", 2275 + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 2276 + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2277 + "license": "MIT", 2278 + "dependencies": { 2279 + "is-number": "^7.0.0" 2280 + }, 2281 + "engines": { 2282 + "node": ">=8.0" 2283 + } 2284 + }, 2285 + "node_modules/toidentifier": { 2286 + "version": "1.0.1", 2287 + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 2288 + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 2289 + "engines": { 2290 + "node": ">=0.6" 2291 + } 2292 + }, 2293 + "node_modules/touch": { 2294 + "version": "3.1.1", 2295 + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", 2296 + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", 2297 + "license": "ISC", 2298 + "bin": { 2299 + "nodetouch": "bin/nodetouch.js" 2300 + } 2301 + }, 2302 + "node_modules/tslib": { 2303 + "version": "2.8.1", 2304 + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", 2305 + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", 2306 + "license": "0BSD", 2307 + "optional": true 2308 + }, 2309 + "node_modules/type-is": { 2310 + "version": "2.0.1", 2311 + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", 2312 + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", 2313 + "dependencies": { 2314 + "content-type": "^1.0.5", 2315 + "media-typer": "^1.1.0", 2316 + "mime-types": "^3.0.0" 2317 + }, 2318 + "engines": { 2319 + "node": ">= 0.6" 2320 + } 2321 + }, 2322 + "node_modules/ufo": { 2323 + "version": "1.6.1", 2324 + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", 2325 + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", 2326 + "license": "MIT" 2327 + }, 2328 + "node_modules/undefsafe": { 2329 + "version": "2.0.5", 2330 + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", 2331 + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", 2332 + "license": "MIT" 2333 + }, 2334 + "node_modules/undici": { 2335 + "version": "7.15.0", 2336 + "resolved": "https://registry.npmjs.org/undici/-/undici-7.15.0.tgz", 2337 + "integrity": "sha512-7oZJCPvvMvTd0OlqWsIxTuItTpJBpU1tcbVl24FMn3xt3+VSunwUasmfPJRE57oNO1KsZ4PgA1xTdAX4hq8NyQ==", 2338 + "license": "MIT", 2339 + "engines": { 2340 + "node": ">=20.18.1" 2341 + } 2342 + }, 2343 + "node_modules/unenv": { 2344 + "version": "2.0.0-rc.19", 2345 + "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.19.tgz", 2346 + "integrity": "sha512-t/OMHBNAkknVCI7bVB9OWjUUAwhVv9vsPIAGnNUxnu3FxPQN11rjh0sksLMzc3g7IlTgvHmOTl4JM7JHpcv5wA==", 2347 + "license": "MIT", 2348 + "dependencies": { 2349 + "defu": "^6.1.4", 2350 + "exsolve": "^1.0.7", 2351 + "ohash": "^2.0.11", 2352 + "pathe": "^2.0.3", 2353 + "ufo": "^1.6.1" 2354 + } 2355 + }, 2356 + "node_modules/unpipe": { 2357 + "version": "1.0.0", 2358 + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 2359 + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 2360 + "engines": { 2361 + "node": ">= 0.8" 2362 + } 2363 + }, 2364 + "node_modules/vary": { 2365 + "version": "1.1.2", 2366 + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 2367 + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 2368 + "engines": { 2369 + "node": ">= 0.8" 2370 + } 2371 + }, 2372 + "node_modules/workerd": { 2373 + "version": "1.20250823.0", 2374 + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20250823.0.tgz", 2375 + "integrity": "sha512-95lToK9zeaC7bX5ZmlP/wz6zqoUPBk3hhec1JjEMGZrxsXY9cPRkjWNCcjDctQ17U97vjMcY/ymchgx7w8Cfmg==", 2376 + "hasInstallScript": true, 2377 + "license": "Apache-2.0", 2378 + "bin": { 2379 + "workerd": "bin/workerd" 2380 + }, 2381 + "engines": { 2382 + "node": ">=16" 2383 + }, 2384 + "optionalDependencies": { 2385 + "@cloudflare/workerd-darwin-64": "1.20250823.0", 2386 + "@cloudflare/workerd-darwin-arm64": "1.20250823.0", 2387 + "@cloudflare/workerd-linux-64": "1.20250823.0", 2388 + "@cloudflare/workerd-linux-arm64": "1.20250823.0", 2389 + "@cloudflare/workerd-windows-64": "1.20250823.0" 2390 + } 2391 + }, 2392 + "node_modules/wrangler": { 2393 + "version": "4.33.0", 2394 + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.33.0.tgz", 2395 + "integrity": "sha512-LIVnW/VePLMca8Y4pKz4ycXc8yPfXwJJnOnpq65fRTh9lR4UAuqHvSNW4Vx4JJI3ZniRZXIM8pb+tSntd5161w==", 2396 + "license": "MIT OR Apache-2.0", 2397 + "dependencies": { 2398 + "@cloudflare/kv-asset-handler": "0.4.0", 2399 + "@cloudflare/unenv-preset": "2.6.3", 2400 + "blake3-wasm": "2.1.5", 2401 + "esbuild": "0.25.4", 2402 + "miniflare": "4.20250823.0", 2403 + "path-to-regexp": "6.3.0", 2404 + "unenv": "2.0.0-rc.19", 2405 + "workerd": "1.20250823.0" 2406 + }, 2407 + "bin": { 2408 + "wrangler": "bin/wrangler.js", 2409 + "wrangler2": "bin/wrangler.js" 2410 + }, 2411 + "engines": { 2412 + "node": ">=18.0.0" 2413 + }, 2414 + "optionalDependencies": { 2415 + "fsevents": "~2.3.2" 2416 + }, 2417 + "peerDependencies": { 2418 + "@cloudflare/workers-types": "^4.20250823.0" 2419 + }, 2420 + "peerDependenciesMeta": { 2421 + "@cloudflare/workers-types": { 2422 + "optional": true 2423 + } 2424 + } 2425 + }, 2426 + "node_modules/wrangler/node_modules/path-to-regexp": { 2427 + "version": "6.3.0", 2428 + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", 2429 + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", 2430 + "license": "MIT" 2431 + }, 2432 + "node_modules/wrappy": { 2433 + "version": "1.0.2", 2434 + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2435 + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" 2436 + }, 2437 + "node_modules/ws": { 2438 + "version": "8.18.0", 2439 + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", 2440 + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", 2441 + "license": "MIT", 2442 + "engines": { 2443 + "node": ">=10.0.0" 2444 + }, 2445 + "peerDependencies": { 2446 + "bufferutil": "^4.0.1", 2447 + "utf-8-validate": ">=5.0.2" 2448 + }, 2449 + "peerDependenciesMeta": { 2450 + "bufferutil": { 2451 + "optional": true 2452 + }, 2453 + "utf-8-validate": { 2454 + "optional": true 2455 + } 2456 + } 2457 + }, 2458 + "node_modules/yaml": { 2459 + "version": "2.8.1", 2460 + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", 2461 + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", 2462 + "license": "ISC", 2463 + "bin": { 2464 + "yaml": "bin.mjs" 2465 + }, 2466 + "engines": { 2467 + "node": ">= 14.6" 2468 + } 2469 + }, 2470 + "node_modules/youch": { 2471 + "version": "4.1.0-beta.10", 2472 + "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.0-beta.10.tgz", 2473 + "integrity": "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==", 2474 + "license": "MIT", 2475 + "dependencies": { 2476 + "@poppinss/colors": "^4.1.5", 2477 + "@poppinss/dumper": "^0.6.4", 2478 + "@speed-highlight/core": "^1.2.7", 2479 + "cookie": "^1.0.2", 2480 + "youch-core": "^0.3.3" 2481 + } 2482 + }, 2483 + "node_modules/youch-core": { 2484 + "version": "0.3.3", 2485 + "resolved": "https://registry.npmjs.org/youch-core/-/youch-core-0.3.3.tgz", 2486 + "integrity": "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==", 2487 + "license": "MIT", 2488 + "dependencies": { 2489 + "@poppinss/exception": "^1.2.2", 2490 + "error-stack-parser-es": "^1.0.5" 2491 + } 2492 + }, 2493 + "node_modules/youch/node_modules/cookie": { 2494 + "version": "1.0.2", 2495 + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", 2496 + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", 2497 + "license": "MIT", 2498 + "engines": { 2499 + "node": ">=18" 2500 + } 2501 + }, 2502 + "node_modules/zod": { 2503 + "version": "3.22.3", 2504 + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.3.tgz", 2505 + "integrity": "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==", 2506 + "license": "MIT", 2507 + "funding": { 2508 + "url": "https://github.com/sponsors/colinhacks" 2509 + } 2510 + } 2511 + } 2512 + }
+18
package.json
··· 1 + { 2 + "name": "tangled-pages", 3 + "version": "1.0.0", 4 + "type": "module", 5 + "scripts": { 6 + "start": "npm run dev", 7 + "dev": "npm run dev:worker", 8 + "dev:worker": "wrangler dev --port 3000 --env development", 9 + "dev:express": "nodemon src/server.js" 10 + }, 11 + "dependencies": { 12 + "dotenv": "^17.2.1", 13 + "express": "^5.1.0", 14 + "nodemon": "^3.1.10", 15 + "wrangler": "^4.33.0", 16 + "yaml": "^2.8.1" 17 + } 18 + }
+68
src/helpers.js
··· 1 + export function getContentTypeForExtension(extension, fallback = "text/plain") { 2 + switch (extension) { 3 + case ".html": 4 + return "text/html"; 5 + case ".css": 6 + return "text/css"; 7 + case ".js": 8 + return "application/javascript"; 9 + case ".json": 10 + return "application/json"; 11 + case ".svg": 12 + return "image/svg+xml"; 13 + case ".png": 14 + return "image/png"; 15 + case ".jpg": 16 + return "image/jpeg"; 17 + case ".gif": 18 + return "image/gif"; 19 + case ".webp": 20 + return "image/webp"; 21 + case ".ico": 22 + return "image/x-icon"; 23 + case ".txt": 24 + return "text/plain"; 25 + case ".md": 26 + return "text/markdown"; 27 + case ".xml": 28 + return "application/xml"; 29 + case ".pdf": 30 + return "application/pdf"; 31 + case ".zip": 32 + return "application/zip"; 33 + case ".7z": 34 + return "application/x-7z-compressed"; 35 + case ".tar": 36 + return "application/x-tar"; 37 + case ".gz": 38 + return "application/gzip"; 39 + case ".bz2": 40 + return "application/x-bzip2"; 41 + case ".mp3": 42 + return "audio/mpeg"; 43 + case ".mp4": 44 + return "video/mp4"; 45 + case ".webm": 46 + return "video/webm"; 47 + case ".ogg": 48 + return "audio/ogg"; 49 + case ".wav": 50 + return "audio/wav"; 51 + case ".flac": 52 + return "audio/flac"; 53 + case ".aac": 54 + return "audio/aac"; 55 + case ".m4a": 56 + return "audio/mp4"; 57 + case ".m4v": 58 + return "video/mp4"; 59 + } 60 + return fallback; 61 + } 62 + 63 + export function trimLeadingSlash(path) { 64 + if (path.startsWith("/")) { 65 + return path.slice(1); 66 + } 67 + return path; 68 + }
+185
src/knot-client.js
··· 1 + // https://tangled.sh/@tangled.sh/core/blob/master/knotclient/unsigned.go 2 + // Converted to JavaScript by Claude Code 3 + // Changes: 4 + // - Added blob method 5 + // - Added verbose option 6 + 7 + class UnsignedClient { 8 + constructor(domain, dev = false, verbose = false) { 9 + this.baseUrl = new URL(`${dev ? "http" : "https"}://${domain}`); 10 + this.verbose = verbose; 11 + } 12 + 13 + async newRequest(method, endpoint, query = null, body = null) { 14 + const url = new URL(endpoint, this.baseUrl); 15 + 16 + if (query) { 17 + for (const [key, value] of Object.entries(query)) { 18 + url.searchParams.append(key, value); 19 + } 20 + } 21 + 22 + const options = { 23 + method, 24 + headers: { 25 + "Content-Type": "application/json", 26 + }, 27 + signal: AbortSignal.timeout(5000), // 5 second timeout 28 + }; 29 + 30 + if (body) { 31 + options.body = typeof body === "string" ? body : JSON.stringify(body); 32 + } 33 + 34 + return { url: url.toString(), options }; 35 + } 36 + 37 + async doRequest(url, options) { 38 + try { 39 + if (this.verbose) { 40 + console.log("Request:", url); 41 + } 42 + 43 + const response = await fetch(url, options); 44 + 45 + if (!response.ok && response.status !== 404 && response.status !== 400) { 46 + throw new Error(`HTTP error! status: ${response.status}`); 47 + } 48 + 49 + const text = await response.text(); 50 + return { 51 + status: response.status, 52 + data: text ? JSON.parse(text) : null, 53 + }; 54 + } catch (error) { 55 + console.error("Request error:", error); 56 + throw error; 57 + } 58 + } 59 + 60 + async index(ownerDid, repoName, ref = "") { 61 + const endpoint = ref 62 + ? `/${ownerDid}/${repoName}/tree/${ref}` 63 + : `/${ownerDid}/${repoName}`; 64 + 65 + const { url, options } = await this.newRequest("GET", endpoint); 66 + const response = await this.doRequest(url, options); 67 + return response.data; 68 + } 69 + 70 + async log(ownerDid, repoName, ref, page = 0) { 71 + const endpoint = `/${ownerDid}/${repoName}/log/${encodeURIComponent(ref)}`; 72 + const query = { 73 + page: page.toString(), 74 + per_page: "60", 75 + }; 76 + 77 + const { url, options } = await this.newRequest("GET", endpoint, query); 78 + const response = await this.doRequest(url, options); 79 + return response.data; 80 + } 81 + 82 + async branches(ownerDid, repoName) { 83 + const endpoint = `/${ownerDid}/${repoName}/branches`; 84 + 85 + const { url, options } = await this.newRequest("GET", endpoint); 86 + const response = await this.doRequest(url, options); 87 + return response.data; 88 + } 89 + 90 + async tags(ownerDid, repoName) { 91 + const endpoint = `/${ownerDid}/${repoName}/tags`; 92 + 93 + const { url, options } = await this.newRequest("GET", endpoint); 94 + const response = await this.doRequest(url, options); 95 + return response.data; 96 + } 97 + 98 + async branch(ownerDid, repoName, branch) { 99 + const endpoint = `/${ownerDid}/${repoName}/branches/${encodeURIComponent( 100 + branch 101 + )}`; 102 + 103 + const { url, options } = await this.newRequest("GET", endpoint); 104 + const response = await this.doRequest(url, options); 105 + return response.data; 106 + } 107 + 108 + async defaultBranch(ownerDid, repoName) { 109 + const endpoint = `/${ownerDid}/${repoName}/branches/default`; 110 + 111 + const { url, options } = await this.newRequest("GET", endpoint); 112 + const response = await this.doRequest(url, options); 113 + return response.data; 114 + } 115 + 116 + async capabilities() { 117 + const endpoint = "/capabilities"; 118 + 119 + const { url, options } = await this.newRequest("GET", endpoint); 120 + const response = await this.doRequest(url, options); 121 + return response.data; 122 + } 123 + 124 + async compare(ownerDid, repoName, rev1, rev2) { 125 + const endpoint = `/${ownerDid}/${repoName}/compare/${encodeURIComponent( 126 + rev1 127 + )}/${encodeURIComponent(rev2)}`; 128 + 129 + const { url, options } = await this.newRequest("GET", endpoint); 130 + 131 + try { 132 + const response = await fetch(url, options); 133 + 134 + if (response.status === 404 || response.status === 400) { 135 + throw new Error("Branch comparisons not supported on this knot."); 136 + } 137 + 138 + if (!response.ok) { 139 + throw new Error("Failed to create request."); 140 + } 141 + 142 + const text = await response.text(); 143 + return JSON.parse(text); 144 + } catch (error) { 145 + console.error("Failed to compare across branches"); 146 + throw new Error("Failed to compare branches."); 147 + } 148 + } 149 + 150 + async repoLanguages(ownerDid, repoName, ref) { 151 + const endpoint = `/${ownerDid}/${repoName}/languages/${encodeURIComponent( 152 + ref 153 + )}`; 154 + 155 + try { 156 + const { url, options } = await this.newRequest("GET", endpoint); 157 + const response = await fetch(url, options); 158 + 159 + if (response.status !== 200) { 160 + console.warn("Failed to calculate languages", response.status); 161 + return {}; 162 + } 163 + 164 + const text = await response.text(); 165 + return JSON.parse(text); 166 + } catch (error) { 167 + console.error("Error fetching repo languages:", error); 168 + throw error; 169 + } 170 + } 171 + 172 + async blob(ownerDid, repoName, ref, filePath) { 173 + const endpoint = `/${ownerDid}/${repoName}/blob/${encodeURIComponent( 174 + ref 175 + )}/${filePath}`; 176 + 177 + const { url, options } = await this.newRequest("GET", endpoint); 178 + const response = await this.doRequest(url, options); 179 + return response.data; 180 + } 181 + } 182 + 183 + export function createUnsignedClient(domain, dev = false, verbose = false) { 184 + return new UnsignedClient(domain, dev, verbose); 185 + }
+161
src/pages-service.js
··· 1 + import { createUnsignedClient } from "./knot-client.js"; 2 + import { getContentTypeForExtension, trimLeadingSlash } from "./helpers.js"; 3 + import path from "node:path"; 4 + import yaml from "yaml"; 5 + 6 + // Helpers 7 + 8 + function getContentTypeForFilename(filename) { 9 + const extension = path.extname(filename).toLowerCase(); 10 + return getContentTypeForExtension(extension); 11 + } 12 + 13 + class FileCache { 14 + constructor({ expirationSeconds = 60 }) { 15 + this.cache = new Map(); 16 + this.expirationSeconds = expirationSeconds; 17 + } 18 + 19 + get(filename) { 20 + if (this.cache.has(filename)) { 21 + const entry = this.cache.get(filename); 22 + if ( 23 + entry && 24 + entry.timestamp > Date.now() - this.expirationSeconds * 1000 25 + ) { 26 + return entry.content; 27 + } 28 + } 29 + return null; 30 + } 31 + 32 + set(filename, content) { 33 + const timestamp = Date.now(); 34 + this.cache.set(filename, { content, timestamp }); 35 + } 36 + } 37 + 38 + class PagesConfig { 39 + constructor({ basePath, notFoundFilepath }) { 40 + this.basePath = basePath; 41 + this.notFoundFilepath = notFoundFilepath; 42 + } 43 + 44 + static default() { 45 + return new PagesConfig({ 46 + basePath: "/", 47 + notFoundFilepath: null, 48 + }); 49 + } 50 + 51 + static fromFile(filePath, fileContent) { 52 + if (!filePath.endsWith(".yaml")) { 53 + throw new Error("Config file must be a YAML file"); 54 + } 55 + let configObj = {}; 56 + try { 57 + configObj = yaml.parse(fileContent); 58 + } catch (error) { 59 + throw new Error(`Error parsing YAML file ${filePath}: ${error}`); 60 + } 61 + return new PagesConfig({ 62 + basePath: configObj.basePath || "/", 63 + notFoundFilepath: configObj.notFoundFilepath || null, 64 + }); 65 + } 66 + } 67 + 68 + class PagesService { 69 + constructor({ 70 + domain, 71 + ownerDid, 72 + repoName, 73 + configFilepath = "pages_config.yaml", 74 + verbose = false, 75 + }) { 76 + this.ownerDid = ownerDid; 77 + this.repoName = repoName; 78 + this.configFilepath = configFilepath; 79 + this.verbose = verbose; 80 + this.client = createUnsignedClient(domain, false, verbose); 81 + this.fileCache = new FileCache({ expirationSeconds: 60 }); 82 + } 83 + 84 + async getConfig() { 85 + if (!this.__config) { 86 + await this.loadConfig(); 87 + } 88 + return this.__config; 89 + } 90 + 91 + async loadConfig() { 92 + let config = null; 93 + const configFileContent = await this.getFileContent(this.configFilepath); 94 + if (!configFileContent) { 95 + console.warn( 96 + `No config file found at ${this.configFilepath}, using default config` 97 + ); 98 + config = PagesConfig.default(); 99 + } else { 100 + config = PagesConfig.fromFile(this.configFilepath, configFileContent); 101 + } 102 + this.__config = config; 103 + return config; 104 + } 105 + 106 + async getFileContent(filename) { 107 + const cachedContent = this.fileCache.get(filename); 108 + if (cachedContent) { 109 + if (this.verbose) { 110 + console.log(`Cache hit for ${filename}`); 111 + } 112 + return cachedContent; 113 + } 114 + // todo error handling? 115 + const blob = await this.client.blob( 116 + this.ownerDid, 117 + this.repoName, 118 + "main", 119 + trimLeadingSlash(filename) 120 + ); 121 + const content = blob.contents; 122 + this.fileCache.set(filename, content); 123 + return content; 124 + } 125 + 126 + async getPage(route) { 127 + const config = await this.getConfig(); 128 + let filePath = route; 129 + const extension = path.extname(filePath); 130 + if (extension === "") { 131 + filePath = path.join(filePath, "index.html"); 132 + } 133 + 134 + const fullPath = path.join(config.basePath, trimLeadingSlash(filePath)); 135 + 136 + const content = await this.getFileContent(fullPath); 137 + if (!content) { 138 + return this.get404(); 139 + } 140 + return { 141 + status: 200, 142 + content, 143 + contentType: getContentTypeForFilename(fullPath), 144 + }; 145 + } 146 + 147 + async get404() { 148 + const { notFoundFilepath } = await this.getConfig(); 149 + if (notFoundFilepath) { 150 + const content = await this.getFileContent(notFoundFilepath); 151 + return { 152 + status: 404, 153 + content, 154 + contentType: getContentTypeForFilename(notFoundFilepath), 155 + }; 156 + } 157 + return { status: 404, content: "Not Found", contentType: "text/plain" }; 158 + } 159 + } 160 + 161 + export default PagesService;
+35
src/server.js
··· 1 + import PagesService from "./pages-service.js"; 2 + import express from "express"; 3 + import dotenv from "dotenv"; 4 + 5 + dotenv.config(); 6 + 7 + const pagesService = new PagesService({ 8 + domain: process.env.KNOT_DOMAIN, 9 + ownerDid: process.env.OWNER_DID, 10 + repoName: process.env.REPO_NAME, 11 + verbose: process.env.NODE_ENV === "development", 12 + }); 13 + 14 + // preload to make sure there are no problems with the config 15 + await pagesService.loadConfig(); 16 + 17 + const app = express(); 18 + 19 + app.get("/{*any}", async (req, res) => { 20 + const route = req.path; 21 + const { status, content, contentType } = await pagesService.getPage(route); 22 + res.status(status).set("Content-Type", contentType).send(content); 23 + }); 24 + 25 + function main() { 26 + const server = app.listen(3000, () => { 27 + console.log("Server is running on port 3000"); 28 + }); 29 + 30 + server.on("error", (error) => { 31 + console.error("Server error:", error); 32 + }); 33 + } 34 + 35 + main();
+30
src/worker.js
··· 1 + import PagesService from "./pages-service.js"; 2 + 3 + let pagesService = null; 4 + 5 + // idk how long cloudflare will keep this around. 6 + // it would be better to save the config in a KV store 7 + // but this is good enough for now 8 + function getPagesService(env) { 9 + if (!pagesService) { 10 + pagesService = new PagesService({ 11 + domain: env.KNOT_DOMAIN, 12 + ownerDid: env.OWNER_DID, 13 + repoName: env.REPO_NAME, 14 + verbose: env.NODE_ENV === "development", 15 + }); 16 + } 17 + return pagesService; 18 + } 19 + 20 + export default { 21 + async fetch(request, env, ctx) { 22 + const route = new URL(request.url).pathname; 23 + const pagesService = getPagesService(env); 24 + const { status, content, contentType } = await pagesService.getPage(route); 25 + return new Response(content, { 26 + status, 27 + headers: { "Content-Type": contentType }, 28 + }); 29 + }, 30 + };
+16
test/knot-client-test.js
··· 1 + import { createUnsignedClient } from "./knot-client.js"; 2 + 3 + const OWNER_DID = "did:plc:p572wxnsuoogcrhlfrlizlrb"; 4 + const REPO_NAME = "static-site-example"; 5 + const KNOT_DOMAIN = "knot.gracekind.net"; 6 + 7 + const client = createUnsignedClient(KNOT_DOMAIN); 8 + 9 + const blob = await client.blob( 10 + OWNER_DID, 11 + REPO_NAME, 12 + "main", 13 + "public/index.html" 14 + ); 15 + 16 + console.log(blob);
+4
wrangler.toml
··· 1 + name = "tangled-pages" 2 + main = "src/worker.js" 3 + compatibility_flags = [ "nodejs_compat" ] 4 + compatibility_date = "2024-09-23"