diff --git a/web/jsconfig.json b/web/jsconfig.json
index 50c36d8..1b28bc8 100644
--- a/web/jsconfig.json
+++ b/web/jsconfig.json
@@ -1,9 +1,9 @@
{
- "extends": "./.svelte-kit/tsconfig.json",
+ "extends": "$app/tsconfig",
"compilerOptions": {
- "allowJs": true,
- "checkJs": false,
- "module": "esnext",
- "moduleResolution": "bundler"
- }
+ "checkJs": false
+ },
+ "include": [
+ "src"
+ ]
}
diff --git a/web/package-lock.json b/web/package-lock.json
index 8affe67..a2446c8 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -9,17 +9,17 @@
"version": "0.1.0",
"devDependencies": {
"@eslint/js": "^10.0.1",
- "@sveltejs/adapter-static": "^3.0.10",
- "@sveltejs/kit": "^2.70.1",
+ "@sveltejs/adapter-static": "^4.0.0",
+ "@sveltejs/kit": "^3.0.0",
"@sveltejs/vite-plugin-svelte": "^7.2.0",
"@tailwindcss/vite": "^4.3.3",
"eslint": "^10",
"eslint-plugin-svelte": "^3.22.0",
"globals": "^17.7.0",
- "svelte": "^5.56.8",
+ "svelte": "^5.57.1",
"tailwindcss": "^4.3.3",
"vite": "^8.1.5",
- "vitest": "^4.1.10"
+ "vitest": "^5.0.3"
}
},
"node_modules/@cacheable/memory": {
@@ -629,47 +629,43 @@
}
},
"node_modules/@sveltejs/adapter-static": {
- "version": "3.0.10",
- "resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-3.0.10.tgz",
- "integrity": "sha512-7D9lYFWJmB7zxZyTE/qxjksvMqzMuYrrsyh1f4AlZqeZeACPRySjbC3aFiY55wb1tWUaKOQG9PVbm74JcN2Iew==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-4.0.0.tgz",
+ "integrity": "sha512-aF1J23R1ebKqUxQ4/qLr/Lxu63NFmLAtg8UZl3HFLxaoA1D/nhTVGcD9lTqx65iUbjNR2iOL0TgOxSX82x6Paw==",
"dev": true,
"license": "MIT",
"peerDependencies": {
- "@sveltejs/kit": "^2.0.0"
+ "@sveltejs/kit": "^3.0.0-next.0"
}
},
"node_modules/@sveltejs/kit": {
- "version": "2.70.3",
- "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.70.3.tgz",
- "integrity": "sha512-UDvEYuZqAMbfB/oXIoqKvbKcb7YczK5zYrzmsGV1zRJk03jntwp8dXiYoIJotxAndsKvcPFtx9H1GRSKFdSHgg==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-3.0.0.tgz",
+ "integrity": "sha512-dmP6gjz41DAT7erONGW8FdTWjmsmOJ/SaWVEsuEc1MXDcpH6YV+Pt98biZFPuinH4LldJPmScxDqiHwCDLRCrg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@standard-schema/spec": "^1.0.0",
- "@sveltejs/acorn-typescript": "^1.0.9",
- "@types/cookie": "^0.6.0",
- "acorn": "^8.16.0",
- "cookie": "^0.6.0",
- "devalue": "^5.8.1",
+ "@rolldown/pluginutils": "^1.0.1",
+ "@standard-schema/spec": "^1.1.0",
+ "cookie": "^2.0.1",
+ "devalue": "^5.9.4",
"esm-env": "^1.2.2",
- "kleur": "^4.1.5",
- "magic-string": "^0.30.5",
- "mrmime": "^2.0.0",
- "set-cookie-parser": "^3.0.0",
- "sirv": "^3.0.0"
+ "magic-string": "^1.2.3",
+ "mrmime": "^2.0.1",
+ "sirv": "^3.0.2"
},
"bin": {
"svelte-kit": "svelte-kit.js"
},
"engines": {
- "node": ">=18.13"
+ "node": ">=22.17"
},
"peerDependencies": {
"@opentelemetry/api": "^1.0.0",
- "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0 || ^7.0.0",
- "svelte": "^4.0.0 || ^5.0.0-next.0",
- "typescript": "^5.3.3 || ^6.0.0",
- "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0 || ^8.0.0"
+ "@sveltejs/vite-plugin-svelte": "^7.0.0",
+ "svelte": "^5.57.1",
+ "typescript": "^6.0.0",
+ "vite": "^8.0.12"
},
"peerDependenciesMeta": {
"@opentelemetry/api": {
@@ -680,6 +676,16 @@
}
}
},
+ "node_modules/@sveltejs/kit/node_modules/magic-string": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.2.tgz",
+ "integrity": "sha512-vG+rjFRj1PqdIBozIxAGMjPlOhaVe+GXpbttY/iSK7rGcJRMlwNJO7dcUwmUqkymsFLJiNGI06t4D7Fr7yRC9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.6.0"
+ }
+ },
"node_modules/@sveltejs/vite-plugin-svelte": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-7.3.1.tgz",
@@ -1005,13 +1011,6 @@
"assertion-error": "^2.0.1"
}
},
- "node_modules/@types/cookie": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
- "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@types/deep-eql": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz",
@@ -1040,34 +1039,17 @@
"dev": true,
"license": "MIT"
},
- "node_modules/@vitest/expect": {
- "version": "4.1.11",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.11.tgz",
- "integrity": "sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@standard-schema/spec": "^1.1.0",
- "@types/chai": "^5.2.2",
- "@vitest/spy": "4.1.11",
- "@vitest/utils": "4.1.11",
- "chai": "^6.2.2",
- "tinyrainbow": "^3.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
"node_modules/@vitest/mocker": {
- "version": "4.1.11",
- "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.11.tgz",
- "integrity": "sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==",
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-5.0.3.tgz",
+ "integrity": "sha512-T8sWAIbkSyAjkwTcaEc3Iu0o9A27X1/kdXrizhZkGuSKScRQtRzclfAMpOTcGdXCsqxeWlpGy3XjqaW8CpLORg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/spy": "4.1.11",
+ "@jridgewell/trace-mapping": "0.3.31",
+ "@vitest/spy": "5.0.3",
"estree-walker": "^3.0.3",
- "magic-string": "^0.30.21"
+ "magic-string": "^1.2.3"
},
"funding": {
"url": "https://opencollective.com/vitest"
@@ -1085,74 +1067,26 @@
}
}
},
- "node_modules/@vitest/pretty-format": {
- "version": "4.1.11",
- "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.11.tgz",
- "integrity": "sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==",
+ "node_modules/@vitest/mocker/node_modules/magic-string": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.2.tgz",
+ "integrity": "sha512-vG+rjFRj1PqdIBozIxAGMjPlOhaVe+GXpbttY/iSK7rGcJRMlwNJO7dcUwmUqkymsFLJiNGI06t4D7Fr7yRC9g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "tinyrainbow": "^3.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/@vitest/runner": {
- "version": "4.1.11",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.11.tgz",
- "integrity": "sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@vitest/utils": "4.1.11",
- "pathe": "^2.0.3"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/@vitest/snapshot": {
- "version": "4.1.11",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.11.tgz",
- "integrity": "sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@vitest/pretty-format": "4.1.11",
- "@vitest/utils": "4.1.11",
- "magic-string": "^0.30.21",
- "pathe": "^2.0.3"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
+ "@jridgewell/sourcemap-codec": "^1.6.0"
}
},
"node_modules/@vitest/spy": {
- "version": "4.1.11",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.11.tgz",
- "integrity": "sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==",
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-5.0.3.tgz",
+ "integrity": "sha512-XhFysQTB8AZ+P4gMi+Lpo99vg2AZi0qKpaB9yXQl37+CaMEAPO3iH/wGVnSyL5MPERiLezpqTVtrR6UZH5GCXg==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://opencollective.com/vitest"
}
},
- "node_modules/@vitest/utils": {
- "version": "4.1.11",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.11.tgz",
- "integrity": "sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@vitest/pretty-format": "4.1.11",
- "convert-source-map": "^2.0.0",
- "tinyrainbow": "^3.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
"node_modules/acorn": {
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz",
@@ -1280,21 +1214,18 @@
"node": ">=6"
}
},
- "node_modules/convert-source-map": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
- "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/cookie": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
- "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-2.0.1.tgz",
+ "integrity": "sha512-yuToqVvRrj6pfDXREyQAAv8SkAEk/8GS3jQRTiUMm66TVtBYmqQeoEjL2Lmq8Rpo6271vH76InTChTitEAm65w==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">= 0.6"
+ "node": ">=22"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
}
},
"node_modules/cross-spawn": {
@@ -1905,16 +1836,6 @@
"@keyv/serialize": "^1.1.1"
}
},
- "node_modules/kleur": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
- "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/known-css-properties": {
"version": "0.37.0",
"resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.37.0.tgz",
@@ -2395,13 +2316,6 @@
"node": ">=8"
}
},
- "node_modules/pathe": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
- "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -2646,13 +2560,6 @@
"node": ">=10"
}
},
- "node_modules/set-cookie-parser": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-3.1.2.tgz",
- "integrity": "sha512-5/r/lTwbJ3zQ+qwdUFZYeRNqda7P5HD8zQKqlSjdGt1/S0cjLAphHusj4Y58ahDtWn/g32xrIS58/ikOvwl0Lw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -2676,13 +2583,6 @@
"node": ">=8"
}
},
- "node_modules/siginfo": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
- "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
- "dev": true,
- "license": "ISC"
- },
"node_modules/sirv": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz",
@@ -2708,13 +2608,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/stackback": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
- "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/std-env": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/std-env/-/std-env-4.3.0.tgz",
@@ -2850,11 +2743,14 @@
}
},
"node_modules/tinybench": {
- "version": "2.9.0",
- "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
- "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-6.2.0.tgz",
+ "integrity": "sha512-78U2TlB2CnVenajOFzf3BKSm0J6oz5L0NV7g32LCPccvYc0lbWvys4d3uUUCS2B1N8PAf2+aekR8i1KbC3HO7Q==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.0.0"
+ }
},
"node_modules/tinyexec": {
"version": "1.3.1",
@@ -2883,16 +2779,6 @@
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
- "node_modules/tinyrainbow": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.2.0.tgz",
- "integrity": "sha512-LgO3D9yZJjApUiuUfl9iFAwrtaX4+lok3wJIqttGoKCHlWUqHqbQpnxCf82L8FjgKsh4iGo78hqJwgL8F6To2A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=14.0.0"
- }
- },
"node_modules/totalist": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz",
@@ -3305,38 +3191,31 @@
}
},
"node_modules/vitest": {
- "version": "4.1.11",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.11.tgz",
- "integrity": "sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==",
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-5.0.3.tgz",
+ "integrity": "sha512-xMw97S3rjdtj5dkVat7jCsqWBpvchs3RlpQctUqwJD0KkERk40vz2fJ77lDwW/Vzh/pk18eItYAzkodhSes3jQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/expect": "4.1.11",
- "@vitest/mocker": "4.1.11",
- "@vitest/pretty-format": "4.1.11",
- "@vitest/runner": "4.1.11",
- "@vitest/snapshot": "4.1.11",
- "@vitest/spy": "4.1.11",
- "@vitest/utils": "4.1.11",
- "es-module-lexer": "^2.0.0",
- "expect-type": "^1.3.0",
- "magic-string": "^0.30.21",
- "obug": "^2.1.1",
- "pathe": "^2.0.3",
- "picomatch": "^4.0.3",
- "std-env": "^4.0.0-rc.1",
- "tinybench": "^2.9.0",
- "tinyexec": "^1.0.2",
- "tinyglobby": "^0.2.15",
- "tinyrainbow": "^3.1.0",
- "vite": "^6.0.0 || ^7.0.0 || ^8.0.0",
- "why-is-node-running": "^2.3.0"
+ "@types/chai": "^5.2.2",
+ "@vitest/mocker": "5.0.3",
+ "chai": "^6.2.2",
+ "es-module-lexer": "^2.3.2",
+ "expect-type": "^1.4.0",
+ "magic-string": "^1.2.3",
+ "obug": "^2.1.4",
+ "picomatch": "^4.0.7",
+ "std-env": "^4.2.0",
+ "tinybench": "^6.1.4",
+ "tinyexec": "^1.3.0",
+ "tinyglobby": "^0.2.17",
+ "why-is-node-running": "3.2.1"
},
"bin": {
"vitest": "vitest.mjs"
},
"engines": {
- "node": "^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": "^22.12.0 || ^24.0.0 || >=26.0.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
@@ -3344,16 +3223,16 @@
"peerDependencies": {
"@edge-runtime/vm": "*",
"@opentelemetry/api": "^1.9.0",
- "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0",
- "@vitest/browser-playwright": "4.1.11",
- "@vitest/browser-preview": "4.1.11",
- "@vitest/browser-webdriverio": "4.1.11",
- "@vitest/coverage-istanbul": "4.1.11",
- "@vitest/coverage-v8": "4.1.11",
- "@vitest/ui": "4.1.11",
+ "@types/node": "^22.0.0 || >=24.0.0",
+ "@vitest/browser-playwright": "5.0.3",
+ "@vitest/browser-preview": "5.0.3",
+ "@vitest/browser-webdriverio": "^5.0.0-beta.5 || >=5.0.0",
+ "@vitest/coverage-istanbul": "5.0.3",
+ "@vitest/coverage-v8": "5.0.3",
+ "@vitest/ui": "5.0.3",
"happy-dom": "*",
"jsdom": "*",
- "vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ "vite": "^6.4.0 || ^7.0.0 || ^8.0.0"
},
"peerDependenciesMeta": {
"@edge-runtime/vm": {
@@ -3394,6 +3273,16 @@
}
}
},
+ "node_modules/vitest/node_modules/magic-string": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.2.tgz",
+ "integrity": "sha512-vG+rjFRj1PqdIBozIxAGMjPlOhaVe+GXpbttY/iSK7rGcJRMlwNJO7dcUwmUqkymsFLJiNGI06t4D7Fr7yRC9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.6.0"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -3411,20 +3300,16 @@
}
},
"node_modules/why-is-node-running": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
- "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-3.2.1.tgz",
+ "integrity": "sha512-Tb2FUhB4vUsGQlfSquQLYkApkuPAFQXGFzxWKHHumVz2dK+X1RUm/HnID4+TfIGYJ1kTcwOaCk/buYCEJr6YjQ==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "siginfo": "^2.0.0",
- "stackback": "0.0.2"
- },
"bin": {
"why-is-node-running": "cli.js"
},
"engines": {
- "node": ">=8"
+ "node": ">=20.11"
}
},
"node_modules/word-wrap": {
diff --git a/web/package.json b/web/package.json
index 63193eb..ab7e516 100644
--- a/web/package.json
+++ b/web/package.json
@@ -13,21 +13,22 @@
},
"devDependencies": {
"@eslint/js": "^10.0.1",
- "@sveltejs/adapter-static": "^3.0.10",
- "@sveltejs/kit": "^2.70.1",
+ "@sveltejs/adapter-static": "^4.0.0",
+ "@sveltejs/kit": "^3.0.0",
"@sveltejs/vite-plugin-svelte": "^7.2.0",
"@tailwindcss/vite": "^4.3.3",
"eslint": "^10",
"eslint-plugin-svelte": "^3.22.0",
"globals": "^17.7.0",
- "svelte": "^5.56.8",
+ "svelte": "^5.57.1",
"tailwindcss": "^4.3.3",
"vite": "^8.1.5",
- "vitest": "^4.1.10"
+ "vitest": "^5.0.3"
},
"overrides": {
- "@babel/core": "^7.29.7",
- "js-yaml": "^4.3.0",
"postcss": ">=8.5.16"
+ },
+ "imports": {
+ "#lib/*": "./src/lib/*"
}
}
diff --git a/web/src/lib/champion-data.js b/web/src/lib/champion-data.js
index 1c32e44..c500682 100644
--- a/web/src/lib/champion-data.js
+++ b/web/src/lib/champion-data.js
@@ -11,7 +11,7 @@ export async function loadChampions() {
if (loadPromise) return loadPromise;
loadPromise = (async () => {
- const response = await fetch(asset("/champions.json"));
+ const response = await fetch(asset("champions.json"));
if (!response.ok) {
loadPromise = null;
throw new Error(`Failed to load champions: ${response.status}`);
diff --git a/web/src/lib/components/champion-search.svelte b/web/src/lib/components/champion-search.svelte
index 59a69ba..512c48c 100644
--- a/web/src/lib/components/champion-search.svelte
+++ b/web/src/lib/components/champion-search.svelte
@@ -1,5 +1,5 @@
diff --git a/web/svelte.config.js b/web/svelte.config.js
deleted file mode 100644
index 78ac63d..0000000
--- a/web/svelte.config.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import adapter from "@sveltejs/adapter-static";
-
-/** @type {import('@sveltejs/kit').Config} */
-const config = {
- kit: {
- // No options: output goes to build/. No fallback either — every route is
- // prerendered, so a fallback page would mask a real prerender failure.
- adapter: adapter(),
- paths: {
- base: process.env.BASE_PATH || "",
- },
- },
-};
-
-export default config;
diff --git a/web/test/champion-data.test.js b/web/test/champion-data.test.js
index d477766..97b7542 100644
--- a/web/test/champion-data.test.js
+++ b/web/test/champion-data.test.js
@@ -1,11 +1,12 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
-import { getChampionImageUrl, getTodaySeed } from "$lib/champion-data";
+import { getChampionImageUrl, getTodaySeed } from "#lib/champion-data.js";
import { AATROX, CHAMPIONS } from "./fixtures/champions";
// $app/paths is a SvelteKit build-time construct with no meaning to a bare
// Vitest run. Base-path behaviour is verified by the production preview check,
-// not here, so the identity stub is the honest unit-test substitute.
-vi.mock("$app/paths", () => ({ asset: (p) => p }));
+// not here, so the stub mirrors asset() with an empty base: it takes a path
+// without a leading slash and returns it root-relative.
+vi.mock("$app/paths", () => ({ asset: (p) => `/${p}` }));
/**
* `champions` is module-private with no reset export, so each group gets a fresh
@@ -19,7 +20,7 @@ async function freshModule({ champions = CHAMPIONS, ok = true, status = 200 } =
json: async () => champions,
}));
vi.stubGlobal("fetch", fetchMock);
- const mod = await import("$lib/champion-data");
+ const mod = await import("#lib/champion-data.js");
return { mod, fetchMock };
}
diff --git a/web/test/classic-mode.test.js b/web/test/classic-mode.test.js
index 05ddaba..8626e69 100644
--- a/web/test/classic-mode.test.js
+++ b/web/test/classic-mode.test.js
@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
-import { CLASSIC_ATTRIBUTES, compareChampions } from "$lib/classic-mode";
+import { CLASSIC_ATTRIBUTES, compareChampions } from "#lib/classic-mode.js";
import { AATROX, AHRI, AKALI, BELVETH } from "./fixtures/champions";
/** Pull one attribute's comparison out of the 7-entry result array. */
diff --git a/web/test/game-engine.test.js b/web/test/game-engine.test.js
index 10d2d50..891e02e 100644
--- a/web/test/game-engine.test.js
+++ b/web/test/game-engine.test.js
@@ -7,7 +7,7 @@ import {
loadUnlimitedStats,
saveUnlimitedStats,
submitGuess,
-} from "$lib/game-engine";
+} from "#lib/game-engine.js";
import { AATROX, AHRI } from "./fixtures/champions";
/** Minimal stand-in for compareChampions — the engine only stores what this returns. */
diff --git a/web/vite.config.js b/web/vite.config.js
index ebfff1b..b158c5a 100644
--- a/web/vite.config.js
+++ b/web/vite.config.js
@@ -1,8 +1,17 @@
+import adapter from "@sveltejs/adapter-static";
import { sveltekit } from "@sveltejs/kit/vite";
import tailwindcss from "@tailwindcss/vite";
import { defineConfig } from "vite";
export default defineConfig({
// tailwindcss() must precede sveltekit(), per the Tailwind v4 SvelteKit guide.
- plugins: [tailwindcss(), sveltekit()],
+ plugins: [
+ tailwindcss(),
+ sveltekit({
+ // No options: output goes to build/. No fallback either — every route is
+ // prerendered, so a fallback page would mask a real prerender failure.
+ adapter: adapter(),
+ paths: { base: process.env.BASE_PATH || "" }
+ })
+ ]
});
diff --git a/web/vitest.config.js b/web/vitest.config.js
index ae15df0..05b3df7 100644
--- a/web/vitest.config.js
+++ b/web/vitest.config.js
@@ -1,13 +1,7 @@
-import { fileURLToPath } from "node:url";
import { defineConfig } from "vitest/config";
+// #lib/* resolves through package.json "imports", so no alias is needed here.
export default defineConfig({
- resolve: {
- // Vitest does not read svelte.config.js, so $lib must be declared here too.
- alias: {
- $lib: fileURLToPath(new URL("./src/lib", import.meta.url)),
- },
- },
test: {
environment: "node",
setupFiles: ["./test/setup-local-storage.js"],