Weather Station / ECOWITT / DNT
0

Configure Feed

Select the types of activity you want to include in your feed.

forecast

+2328 -708
+52 -2
README.md
··· 140 140 - `GET /api/config/channels` 141 141 - Returns `channels.json`. 142 142 143 - All API routes run in the Node.js runtime and read from the local filesystem. 143 + - Forecast (Geosphere API + OpenWeatherMap + Meteoblue) 144 + - `GET /api/forecast?action=stations` 145 + - Returns TAWES weather stations grouped by Austrian states. 146 + - `GET /api/forecast?action=forecast&stationId=<ID>` 147 + - Returns temperature, precipitation, and wind forecast for the specified station (next ~60 hours). 148 + - Data source: Geosphere Austria ensemble forecast API (C-LAEF model). 149 + - `GET /api/forecast?action=openweather&stationId=<ID>` 150 + - Returns 5-day daily forecast for the specified station location. 151 + - Data source: OpenWeatherMap 5 Day / 3 Hour Forecast API (FREE). 152 + - Aggregates 3-hour forecasts into daily summaries. 153 + - Requires `OPENWEATHER_API_KEY` environment variable. 154 + - `GET /api/forecast?action=meteoblue&stationId=<ID>` 155 + - Returns 7-day daily forecast for the specified station location. 156 + - Data source: Meteoblue basic-day package (FREE for non-commercial use). 157 + - Requires `METEOBLUE_API_KEY` environment variable. 158 + - `GET /api/forecast?action=meteogram&stationId=<ID>` 159 + - Returns meteogram image (14-day detailed forecast visualization). 160 + - Data source: Meteoblue meteogram image API (FREE for non-commercial use). 161 + - Returns WebP image format. 162 + - Requires `METEOBLUE_API_KEY` environment variable. 163 + 164 + All API routes run in the Node.js runtime and read from the local filesystem (except forecast, which fetches from external Geosphere API). 144 165 145 166 ### Statistics (precomputed) 146 167 ··· 239 260 240 261 ## Data (Ecowitt API v3) 241 262 242 - The homepage is split into three tabs: 263 + The homepage is split into four tabs: 243 264 244 265 - **Realtime (Echtzeit)**: Fetches live data from Ecowitt API v3 via a server-side proxy (`/api/rt/last`). Values are shown as key metrics and as gauges/charts. 245 266 - **Grafik**: Visual, realtime gauges for the station: outdoor temperature and humidity (with gradient guides), wind compass with speed/gust, barometric pressure, rainfall KPIs (rate/hour/day/week/month/year), solar radiation, UV index, indoor temperature/humidity, plus mini‑gauges for CH1–CH8. ··· 249 270 - Optional global time range: enable “Ausgewählten Zeitraum verwenden” to pick start/end and query across months. 250 271 - Charts are interactive (zoom/pan/reset) and labels are localized. 251 272 - Channel names are configurable via `src/config/channels.json`. 273 + - **Prognose (Forecast)**: Triple weather forecast display from three independent sources. 274 + - **Geosphere Austria** 🇦🇹: Short-term forecast (~2.5 days / 60 hours) 275 + - Temperature (min/max/avg), precipitation, and wind speed 276 + - Data source: Geosphere API ensemble forecast (C-LAEF model) with 1-hour resolution 277 + - **OpenWeatherMap** 🌍: Extended 5-day forecast (FREE API) 278 + - Temperature (min/max/day), precipitation with probability, wind speed and gusts 279 + - Weather icons and descriptions 280 + - Uses free 5 Day / 3 Hour Forecast API (aggregated to daily) 281 + - Requires `OPENWEATHER_API_KEY` in `.env` (free API key from openweathermap.org) 282 + - **Meteoblue** 🇨🇭: Extended 7-day forecast + 14-day meteogram (FREE API for non-commercial use) 283 + - Temperature (min/max/mean), precipitation, wind speed and gusts 284 + - Weather pictograms from Meteoblue 285 + - Detailed 14-day meteogram visualization with hourly data 286 + - Uses free basic-day package and meteogram image API 287 + - Requires `METEOBLUE_API_KEY` in `.env` (free API key from meteoblue.com) 288 + - Station selection dropdown grouped by Austrian states (Bundesländer) 289 + - Last selected station is saved in localStorage 290 + - Color-coded display: red for max temperature, blue for min temperature and precipitation 252 291 253 292 ### Backend Realtime Processing 254 293 ··· 474 513 475 514 ```bash 476 515 curl 'http://localhost:3000/api/config/channels' 516 + ``` 517 + 518 + - Forecast (Geosphere API + OpenWeatherMap + Meteoblue) 519 + 520 + ```bash 521 + curl 'http://localhost:3000/api/forecast?action=stations' 522 + curl 'http://localhost:3000/api/forecast?action=forecast&stationId=11035' 523 + curl 'http://localhost:3000/api/forecast?action=openweather&stationId=11035' 524 + curl 'http://localhost:3000/api/forecast?action=meteoblue&stationId=11035' 525 + # Get meteogram image (returns WebP image) 526 + curl 'http://localhost:3000/api/forecast?action=meteogram&stationId=11035' > meteogram.webp 477 527 ``` 478 528 479 529 ## Troubleshooting
+8
env.example
··· 6 6 NEXT_PUBLIC_RT_REFRESH_MS=300000 7 7 ## Only if you also want the API route (/api/rt) to write to DNT (normally OFF to avoid duplicates): set to 1 to enable 8 8 # RT_ARCHIVE_FROM_API=1 9 + 10 + ## OpenWeatherMap API Key for 5-day forecast (FREE - get key at https://openweathermap.org/api) 11 + ## Uses the free "5 Day / 3 Hour Forecast" API 12 + OPENWEATHER_API_KEY=your_api_key_here 13 + 14 + ## Meteoblue API Key for 7-14 day forecast (FREE - get key at https://www.meteoblue.com/en/weather-api) 15 + ## Register for free, confirm non-commercial use, and get instant access 16 + METEOBLUE_API_KEY=your_api_key_here
+1019 -616
package-lock.json
··· 8 8 "name": "ecowitt-nextjs15", 9 9 "version": "0.1.0", 10 10 "dependencies": { 11 - "@duckdb/node-api": "^1.3.2-alpha.25", 11 + "@duckdb/node-api": "^1.4.1-r.4", 12 12 "@heroicons/react": "^2.2.0", 13 - "chart.js": "^4.5.0", 13 + "chart.js": "^4.5.1", 14 14 "chartjs-plugin-zoom": "^2.2.0", 15 - "i18next": "^25.3.6", 16 - "next": "15.4.6", 17 - "react": "19.1.1", 18 - "react-dom": "19.1.1", 19 - "react-i18next": "^15.6.1", 15 + "i18next": "^25.6.0", 16 + "next": "16.0.1", 17 + "react": "19.2.0", 18 + "react-dom": "19.2.0", 19 + "react-i18next": "^16.2.3", 20 20 "suncalc": "^1.9.0" 21 21 }, 22 22 "devDependencies": { ··· 24 24 "@types/node": "^24", 25 25 "@types/react": "^19", 26 26 "@types/react-dom": "^19", 27 - "eslint": "9.33.0", 28 - "eslint-config-next": "15.4.6", 27 + "eslint": "9.39.0", 28 + "eslint-config-next": "16.0.1", 29 29 "tailwindcss": "^4", 30 - "tsx": "^4.7.0", 30 + "tsx": "^4.20.6", 31 31 "typescript": "^5" 32 32 } 33 33 }, ··· 44 44 "url": "https://github.com/sponsors/sindresorhus" 45 45 } 46 46 }, 47 - "node_modules/@ampproject/remapping": { 48 - "version": "2.3.0", 49 - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", 50 - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", 47 + "node_modules/@babel/code-frame": { 48 + "version": "7.27.1", 49 + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", 50 + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", 51 + "dev": true, 52 + "license": "MIT", 53 + "dependencies": { 54 + "@babel/helper-validator-identifier": "^7.27.1", 55 + "js-tokens": "^4.0.0", 56 + "picocolors": "^1.1.1" 57 + }, 58 + "engines": { 59 + "node": ">=6.9.0" 60 + } 61 + }, 62 + "node_modules/@babel/compat-data": { 63 + "version": "7.28.5", 64 + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", 65 + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", 66 + "dev": true, 67 + "license": "MIT", 68 + "engines": { 69 + "node": ">=6.9.0" 70 + } 71 + }, 72 + "node_modules/@babel/core": { 73 + "version": "7.28.5", 74 + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", 75 + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", 76 + "dev": true, 77 + "license": "MIT", 78 + "dependencies": { 79 + "@babel/code-frame": "^7.27.1", 80 + "@babel/generator": "^7.28.5", 81 + "@babel/helper-compilation-targets": "^7.27.2", 82 + "@babel/helper-module-transforms": "^7.28.3", 83 + "@babel/helpers": "^7.28.4", 84 + "@babel/parser": "^7.28.5", 85 + "@babel/template": "^7.27.2", 86 + "@babel/traverse": "^7.28.5", 87 + "@babel/types": "^7.28.5", 88 + "@jridgewell/remapping": "^2.3.5", 89 + "convert-source-map": "^2.0.0", 90 + "debug": "^4.1.0", 91 + "gensync": "^1.0.0-beta.2", 92 + "json5": "^2.2.3", 93 + "semver": "^6.3.1" 94 + }, 95 + "engines": { 96 + "node": ">=6.9.0" 97 + }, 98 + "funding": { 99 + "type": "opencollective", 100 + "url": "https://opencollective.com/babel" 101 + } 102 + }, 103 + "node_modules/@babel/core/node_modules/json5": { 104 + "version": "2.2.3", 105 + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", 106 + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", 107 + "dev": true, 108 + "license": "MIT", 109 + "bin": { 110 + "json5": "lib/cli.js" 111 + }, 112 + "engines": { 113 + "node": ">=6" 114 + } 115 + }, 116 + "node_modules/@babel/core/node_modules/semver": { 117 + "version": "6.3.1", 118 + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", 119 + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", 120 + "dev": true, 121 + "license": "ISC", 122 + "bin": { 123 + "semver": "bin/semver.js" 124 + } 125 + }, 126 + "node_modules/@babel/generator": { 127 + "version": "7.28.5", 128 + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", 129 + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", 130 + "dev": true, 131 + "license": "MIT", 132 + "dependencies": { 133 + "@babel/parser": "^7.28.5", 134 + "@babel/types": "^7.28.5", 135 + "@jridgewell/gen-mapping": "^0.3.12", 136 + "@jridgewell/trace-mapping": "^0.3.28", 137 + "jsesc": "^3.0.2" 138 + }, 139 + "engines": { 140 + "node": ">=6.9.0" 141 + } 142 + }, 143 + "node_modules/@babel/helper-compilation-targets": { 144 + "version": "7.27.2", 145 + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", 146 + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", 147 + "dev": true, 148 + "license": "MIT", 149 + "dependencies": { 150 + "@babel/compat-data": "^7.27.2", 151 + "@babel/helper-validator-option": "^7.27.1", 152 + "browserslist": "^4.24.0", 153 + "lru-cache": "^5.1.1", 154 + "semver": "^6.3.1" 155 + }, 156 + "engines": { 157 + "node": ">=6.9.0" 158 + } 159 + }, 160 + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { 161 + "version": "6.3.1", 162 + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", 163 + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", 164 + "dev": true, 165 + "license": "ISC", 166 + "bin": { 167 + "semver": "bin/semver.js" 168 + } 169 + }, 170 + "node_modules/@babel/helper-globals": { 171 + "version": "7.28.0", 172 + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", 173 + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", 174 + "dev": true, 175 + "license": "MIT", 176 + "engines": { 177 + "node": ">=6.9.0" 178 + } 179 + }, 180 + "node_modules/@babel/helper-module-imports": { 181 + "version": "7.27.1", 182 + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", 183 + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", 184 + "dev": true, 185 + "license": "MIT", 186 + "dependencies": { 187 + "@babel/traverse": "^7.27.1", 188 + "@babel/types": "^7.27.1" 189 + }, 190 + "engines": { 191 + "node": ">=6.9.0" 192 + } 193 + }, 194 + "node_modules/@babel/helper-module-transforms": { 195 + "version": "7.28.3", 196 + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", 197 + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", 198 + "dev": true, 199 + "license": "MIT", 200 + "dependencies": { 201 + "@babel/helper-module-imports": "^7.27.1", 202 + "@babel/helper-validator-identifier": "^7.27.1", 203 + "@babel/traverse": "^7.28.3" 204 + }, 205 + "engines": { 206 + "node": ">=6.9.0" 207 + }, 208 + "peerDependencies": { 209 + "@babel/core": "^7.0.0" 210 + } 211 + }, 212 + "node_modules/@babel/helper-string-parser": { 213 + "version": "7.27.1", 214 + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", 215 + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", 216 + "dev": true, 217 + "license": "MIT", 218 + "engines": { 219 + "node": ">=6.9.0" 220 + } 221 + }, 222 + "node_modules/@babel/helper-validator-identifier": { 223 + "version": "7.28.5", 224 + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", 225 + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", 226 + "dev": true, 227 + "license": "MIT", 228 + "engines": { 229 + "node": ">=6.9.0" 230 + } 231 + }, 232 + "node_modules/@babel/helper-validator-option": { 233 + "version": "7.27.1", 234 + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", 235 + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", 236 + "dev": true, 237 + "license": "MIT", 238 + "engines": { 239 + "node": ">=6.9.0" 240 + } 241 + }, 242 + "node_modules/@babel/helpers": { 243 + "version": "7.28.4", 244 + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", 245 + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", 51 246 "dev": true, 52 - "license": "Apache-2.0", 247 + "license": "MIT", 53 248 "dependencies": { 54 - "@jridgewell/gen-mapping": "^0.3.5", 55 - "@jridgewell/trace-mapping": "^0.3.24" 249 + "@babel/template": "^7.27.2", 250 + "@babel/types": "^7.28.4" 251 + }, 252 + "engines": { 253 + "node": ">=6.9.0" 254 + } 255 + }, 256 + "node_modules/@babel/parser": { 257 + "version": "7.28.5", 258 + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", 259 + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", 260 + "dev": true, 261 + "license": "MIT", 262 + "dependencies": { 263 + "@babel/types": "^7.28.5" 264 + }, 265 + "bin": { 266 + "parser": "bin/babel-parser.js" 56 267 }, 57 268 "engines": { 58 269 "node": ">=6.0.0" ··· 67 278 "node": ">=6.9.0" 68 279 } 69 280 }, 281 + "node_modules/@babel/template": { 282 + "version": "7.27.2", 283 + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", 284 + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", 285 + "dev": true, 286 + "license": "MIT", 287 + "dependencies": { 288 + "@babel/code-frame": "^7.27.1", 289 + "@babel/parser": "^7.27.2", 290 + "@babel/types": "^7.27.1" 291 + }, 292 + "engines": { 293 + "node": ">=6.9.0" 294 + } 295 + }, 296 + "node_modules/@babel/traverse": { 297 + "version": "7.28.5", 298 + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", 299 + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", 300 + "dev": true, 301 + "license": "MIT", 302 + "dependencies": { 303 + "@babel/code-frame": "^7.27.1", 304 + "@babel/generator": "^7.28.5", 305 + "@babel/helper-globals": "^7.28.0", 306 + "@babel/parser": "^7.28.5", 307 + "@babel/template": "^7.27.2", 308 + "@babel/types": "^7.28.5", 309 + "debug": "^4.3.1" 310 + }, 311 + "engines": { 312 + "node": ">=6.9.0" 313 + } 314 + }, 315 + "node_modules/@babel/types": { 316 + "version": "7.28.5", 317 + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", 318 + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", 319 + "dev": true, 320 + "license": "MIT", 321 + "dependencies": { 322 + "@babel/helper-string-parser": "^7.27.1", 323 + "@babel/helper-validator-identifier": "^7.28.5" 324 + }, 325 + "engines": { 326 + "node": ">=6.9.0" 327 + } 328 + }, 70 329 "node_modules/@duckdb/node-api": { 71 - "version": "1.3.2-alpha.25", 72 - "resolved": "https://registry.npmjs.org/@duckdb/node-api/-/node-api-1.3.2-alpha.25.tgz", 73 - "integrity": "sha512-AzDyyjTtnYUxoy/MHDFRwfOggDOkS8RBgGA82OI6nla8B9NDNZeAYJ97T3PvCL8cx7y00EtGVN3g03aoW4fRmw==", 330 + "version": "1.4.1-r.4", 331 + "resolved": "https://registry.npmjs.org/@duckdb/node-api/-/node-api-1.4.1-r.4.tgz", 332 + "integrity": "sha512-dvlkGZBlQBKzt5CDP2lv8stppufCCxK3RWbRGBjg8KHuGxreLNIKN1uzB4p6qpJuMZsD5N8UJd0dqidoKOZ/cw==", 74 333 "license": "MIT", 75 334 "dependencies": { 76 - "@duckdb/node-bindings": "1.3.2-alpha.25" 335 + "@duckdb/node-bindings": "1.4.1-r.4" 77 336 } 78 337 }, 79 338 "node_modules/@duckdb/node-bindings": { 80 - "version": "1.3.2-alpha.25", 81 - "resolved": "https://registry.npmjs.org/@duckdb/node-bindings/-/node-bindings-1.3.2-alpha.25.tgz", 82 - "integrity": "sha512-FkoSaoeRAi6Em0hs0qzr3SN04ykN99R+Qap5kLwhi6GNPnHzWMU1VrNpK9cE4eBj0n+RWlNK0TiO712dn44QzQ==", 339 + "version": "1.4.1-r.4", 340 + "resolved": "https://registry.npmjs.org/@duckdb/node-bindings/-/node-bindings-1.4.1-r.4.tgz", 341 + "integrity": "sha512-dlVzEH1Hizi1LxxiLOs9hpBhvH7mEWQA6ayJ/6NZQbru//UdmjKg27//4+Rbbg2+dF0E9CebOefxlAkKFWi3uA==", 83 342 "license": "MIT", 84 343 "optionalDependencies": { 85 - "@duckdb/node-bindings-darwin-arm64": "1.3.2-alpha.25", 86 - "@duckdb/node-bindings-darwin-x64": "1.3.2-alpha.25", 87 - "@duckdb/node-bindings-linux-arm64": "1.3.2-alpha.25", 88 - "@duckdb/node-bindings-linux-x64": "1.3.2-alpha.25", 89 - "@duckdb/node-bindings-win32-x64": "1.3.2-alpha.25" 344 + "@duckdb/node-bindings-darwin-arm64": "1.4.1-r.4", 345 + "@duckdb/node-bindings-darwin-x64": "1.4.1-r.4", 346 + "@duckdb/node-bindings-linux-arm64": "1.4.1-r.4", 347 + "@duckdb/node-bindings-linux-x64": "1.4.1-r.4", 348 + "@duckdb/node-bindings-win32-x64": "1.4.1-r.4" 90 349 } 91 350 }, 92 351 "node_modules/@duckdb/node-bindings-darwin-arm64": { 93 - "version": "1.3.2-alpha.25", 94 - "resolved": "https://registry.npmjs.org/@duckdb/node-bindings-darwin-arm64/-/node-bindings-darwin-arm64-1.3.2-alpha.25.tgz", 95 - "integrity": "sha512-vRjzNgkz2TAYW5c2rzPwcHBctBWr0lxQ4blFASAv0DdeGPOeuCMXJUA3982X7iPNwAppH0VMII6cYzON0GA+RA==", 352 + "version": "1.4.1-r.4", 353 + "resolved": "https://registry.npmjs.org/@duckdb/node-bindings-darwin-arm64/-/node-bindings-darwin-arm64-1.4.1-r.4.tgz", 354 + "integrity": "sha512-4ZklLdqX5ZqqR0guwVj5DTTwIEL/o0aqJSWBU4loMbOSAZOLANVMG8+x9YJXI3aJjbQ+90VAzJN3ptJs3X1Ong==", 96 355 "cpu": [ 97 356 "arm64" 98 357 ], ··· 103 362 ] 104 363 }, 105 364 "node_modules/@duckdb/node-bindings-darwin-x64": { 106 - "version": "1.3.2-alpha.25", 107 - "resolved": "https://registry.npmjs.org/@duckdb/node-bindings-darwin-x64/-/node-bindings-darwin-x64-1.3.2-alpha.25.tgz", 108 - "integrity": "sha512-BSg/DZjT25QZe87+pmdMfE1XlHdi2WxtAO+F2PEXN6VnPeLyTdl5bYlnhOGrDKquKDmUEqok5OwF7mR4QfU+Aw==", 365 + "version": "1.4.1-r.4", 366 + "resolved": "https://registry.npmjs.org/@duckdb/node-bindings-darwin-x64/-/node-bindings-darwin-x64-1.4.1-r.4.tgz", 367 + "integrity": "sha512-tSWkNzXRjndWNMWJLJzOymGc8gscG2rwYf7wDm6r+e80f0VwrjP1bcNKB/qdKdmubkz1yRU/TWoVEpaK42266A==", 109 368 "cpu": [ 110 369 "x64" 111 370 ], ··· 116 375 ] 117 376 }, 118 377 "node_modules/@duckdb/node-bindings-linux-arm64": { 119 - "version": "1.3.2-alpha.25", 120 - "resolved": "https://registry.npmjs.org/@duckdb/node-bindings-linux-arm64/-/node-bindings-linux-arm64-1.3.2-alpha.25.tgz", 121 - "integrity": "sha512-VhjUH/AvolZWDX/URqiIh58JbAB1vYbDgSmQ0wvqhS9jzJ9Sj88urGDw+XWXw49Rr4BhIgDtX70SoARhO2i/Gg==", 378 + "version": "1.4.1-r.4", 379 + "resolved": "https://registry.npmjs.org/@duckdb/node-bindings-linux-arm64/-/node-bindings-linux-arm64-1.4.1-r.4.tgz", 380 + "integrity": "sha512-RO7M85r+bK0Cvn9lD+304gFl3V2eHK47qnmlGCu7kFPHCAowGCYosKim9ML5FslD3ZBdghGl4AdNnrtY3i3mgQ==", 122 381 "cpu": [ 123 382 "arm64" 124 383 ], ··· 129 388 ] 130 389 }, 131 390 "node_modules/@duckdb/node-bindings-linux-x64": { 132 - "version": "1.3.2-alpha.25", 133 - "resolved": "https://registry.npmjs.org/@duckdb/node-bindings-linux-x64/-/node-bindings-linux-x64-1.3.2-alpha.25.tgz", 134 - "integrity": "sha512-raav2ypBiV4TlpnKU9hocsuFDO4ipwIcQQmkMIh20/Qd9vkv35QcQYNqStiZVJh2LAaVoQffNvcKMlclblYqUQ==", 391 + "version": "1.4.1-r.4", 392 + "resolved": "https://registry.npmjs.org/@duckdb/node-bindings-linux-x64/-/node-bindings-linux-x64-1.4.1-r.4.tgz", 393 + "integrity": "sha512-jQKjaje/z35oUdYv7gvCyqZTpsgskgTyt1vyLCnGV/Kwi6UevzorvwEmpvglqxaMONvRQvoGZykfSzHc2ZlS5w==", 135 394 "cpu": [ 136 395 "x64" 137 396 ], ··· 142 401 ] 143 402 }, 144 403 "node_modules/@duckdb/node-bindings-win32-x64": { 145 - "version": "1.3.2-alpha.25", 146 - "resolved": "https://registry.npmjs.org/@duckdb/node-bindings-win32-x64/-/node-bindings-win32-x64-1.3.2-alpha.25.tgz", 147 - "integrity": "sha512-/fAKax+xYkdRhkUl3PkL3HfFd1ZsezG1yiOkL0StHBdD3xB80Njm1JGHxx1fO3WWE5XTbE1MTJ5I0xjEzPwsfQ==", 404 + "version": "1.4.1-r.4", 405 + "resolved": "https://registry.npmjs.org/@duckdb/node-bindings-win32-x64/-/node-bindings-win32-x64-1.4.1-r.4.tgz", 406 + "integrity": "sha512-IgwffRzZxYmsys6VD3zE3Zd6M9Ld24pNuP/h2eNQL6aY+kRa47R5ULEQ2E8BDFuB+ZIu680XQK5lNG+sW4DTNg==", 148 407 "cpu": [ 149 408 "x64" 150 409 ], ··· 167 426 } 168 427 }, 169 428 "node_modules/@emnapi/runtime": { 170 - "version": "1.4.5", 171 - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz", 172 - "integrity": "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==", 429 + "version": "1.6.0", 430 + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.6.0.tgz", 431 + "integrity": "sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA==", 173 432 "license": "MIT", 174 433 "optional": true, 175 434 "dependencies": { ··· 630 889 } 631 890 }, 632 891 "node_modules/@eslint-community/eslint-utils": { 633 - "version": "4.7.0", 634 - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", 635 - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", 892 + "version": "4.9.0", 893 + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", 894 + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", 636 895 "dev": true, 637 896 "license": "MIT", 638 897 "dependencies": { ··· 672 931 } 673 932 }, 674 933 "node_modules/@eslint/config-array": { 675 - "version": "0.21.0", 676 - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", 677 - "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", 934 + "version": "0.21.1", 935 + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", 936 + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", 678 937 "dev": true, 679 938 "license": "Apache-2.0", 680 939 "dependencies": { 681 - "@eslint/object-schema": "^2.1.6", 940 + "@eslint/object-schema": "^2.1.7", 682 941 "debug": "^4.3.1", 683 942 "minimatch": "^3.1.2" 684 943 }, ··· 687 946 } 688 947 }, 689 948 "node_modules/@eslint/config-helpers": { 690 - "version": "0.3.1", 691 - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", 692 - "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", 949 + "version": "0.4.2", 950 + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", 951 + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", 693 952 "dev": true, 694 953 "license": "Apache-2.0", 954 + "dependencies": { 955 + "@eslint/core": "^0.17.0" 956 + }, 695 957 "engines": { 696 958 "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 697 959 } 698 960 }, 699 961 "node_modules/@eslint/core": { 700 - "version": "0.15.2", 701 - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", 702 - "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", 962 + "version": "0.17.0", 963 + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", 964 + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", 703 965 "dev": true, 704 966 "license": "Apache-2.0", 705 967 "dependencies": { ··· 734 996 } 735 997 }, 736 998 "node_modules/@eslint/js": { 737 - "version": "9.33.0", 738 - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.33.0.tgz", 739 - "integrity": "sha512-5K1/mKhWaMfreBGJTwval43JJmkip0RmM+3+IuqupeSKNC/Th2Kc7ucaq5ovTSra/OOKB9c58CGSz3QMVbWt0A==", 999 + "version": "9.39.0", 1000 + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.0.tgz", 1001 + "integrity": "sha512-BIhe0sW91JGPiaF1mOuPy5v8NflqfjIcDNpC+LbW9f609WVRX1rArrhi6Z2ymvrAry9jw+5POTj4t2t62o8Bmw==", 740 1002 "dev": true, 741 1003 "license": "MIT", 742 1004 "engines": { ··· 747 1009 } 748 1010 }, 749 1011 "node_modules/@eslint/object-schema": { 750 - "version": "2.1.6", 751 - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", 752 - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", 1012 + "version": "2.1.7", 1013 + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", 1014 + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", 753 1015 "dev": true, 754 1016 "license": "Apache-2.0", 755 1017 "engines": { ··· 757 1019 } 758 1020 }, 759 1021 "node_modules/@eslint/plugin-kit": { 760 - "version": "0.3.5", 761 - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", 762 - "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", 1022 + "version": "0.4.1", 1023 + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", 1024 + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", 763 1025 "dev": true, 764 1026 "license": "Apache-2.0", 765 1027 "dependencies": { 766 - "@eslint/core": "^0.15.2", 1028 + "@eslint/core": "^0.17.0", 767 1029 "levn": "^0.4.1" 768 1030 }, 769 1031 "engines": { ··· 845 1107 "url": "https://github.com/sponsors/nzakas" 846 1108 } 847 1109 }, 1110 + "node_modules/@img/colour": { 1111 + "version": "1.0.0", 1112 + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", 1113 + "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", 1114 + "license": "MIT", 1115 + "optional": true, 1116 + "engines": { 1117 + "node": ">=18" 1118 + } 1119 + }, 848 1120 "node_modules/@img/sharp-darwin-arm64": { 849 - "version": "0.34.3", 850 - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.3.tgz", 851 - "integrity": "sha512-ryFMfvxxpQRsgZJqBd4wsttYQbCxsJksrv9Lw/v798JcQ8+w84mBWuXwl+TT0WJ/WrYOLaYpwQXi3sA9nTIaIg==", 1121 + "version": "0.34.4", 1122 + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.4.tgz", 1123 + "integrity": "sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==", 852 1124 "cpu": [ 853 1125 "arm64" 854 1126 ], ··· 864 1136 "url": "https://opencollective.com/libvips" 865 1137 }, 866 1138 "optionalDependencies": { 867 - "@img/sharp-libvips-darwin-arm64": "1.2.0" 1139 + "@img/sharp-libvips-darwin-arm64": "1.2.3" 868 1140 } 869 1141 }, 870 1142 "node_modules/@img/sharp-darwin-x64": { 871 - "version": "0.34.3", 872 - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.3.tgz", 873 - "integrity": "sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA==", 1143 + "version": "0.34.4", 1144 + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.4.tgz", 1145 + "integrity": "sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==", 874 1146 "cpu": [ 875 1147 "x64" 876 1148 ], ··· 886 1158 "url": "https://opencollective.com/libvips" 887 1159 }, 888 1160 "optionalDependencies": { 889 - "@img/sharp-libvips-darwin-x64": "1.2.0" 1161 + "@img/sharp-libvips-darwin-x64": "1.2.3" 890 1162 } 891 1163 }, 892 1164 "node_modules/@img/sharp-libvips-darwin-arm64": { 893 - "version": "1.2.0", 894 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.0.tgz", 895 - "integrity": "sha512-sBZmpwmxqwlqG9ueWFXtockhsxefaV6O84BMOrhtg/YqbTaRdqDE7hxraVE3y6gVM4eExmfzW4a8el9ArLeEiQ==", 1165 + "version": "1.2.3", 1166 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.3.tgz", 1167 + "integrity": "sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==", 896 1168 "cpu": [ 897 1169 "arm64" 898 1170 ], ··· 906 1178 } 907 1179 }, 908 1180 "node_modules/@img/sharp-libvips-darwin-x64": { 909 - "version": "1.2.0", 910 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.0.tgz", 911 - "integrity": "sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg==", 1181 + "version": "1.2.3", 1182 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.3.tgz", 1183 + "integrity": "sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==", 912 1184 "cpu": [ 913 1185 "x64" 914 1186 ], ··· 922 1194 } 923 1195 }, 924 1196 "node_modules/@img/sharp-libvips-linux-arm": { 925 - "version": "1.2.0", 926 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.0.tgz", 927 - "integrity": "sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw==", 1197 + "version": "1.2.3", 1198 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.3.tgz", 1199 + "integrity": "sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==", 928 1200 "cpu": [ 929 1201 "arm" 930 1202 ], ··· 938 1210 } 939 1211 }, 940 1212 "node_modules/@img/sharp-libvips-linux-arm64": { 941 - "version": "1.2.0", 942 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.0.tgz", 943 - "integrity": "sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA==", 1213 + "version": "1.2.3", 1214 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.3.tgz", 1215 + "integrity": "sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==", 944 1216 "cpu": [ 945 1217 "arm64" 946 1218 ], ··· 954 1226 } 955 1227 }, 956 1228 "node_modules/@img/sharp-libvips-linux-ppc64": { 957 - "version": "1.2.0", 958 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.0.tgz", 959 - "integrity": "sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ==", 1229 + "version": "1.2.3", 1230 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.3.tgz", 1231 + "integrity": "sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==", 960 1232 "cpu": [ 961 1233 "ppc64" 962 1234 ], ··· 970 1242 } 971 1243 }, 972 1244 "node_modules/@img/sharp-libvips-linux-s390x": { 973 - "version": "1.2.0", 974 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.0.tgz", 975 - "integrity": "sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw==", 1245 + "version": "1.2.3", 1246 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.3.tgz", 1247 + "integrity": "sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==", 976 1248 "cpu": [ 977 1249 "s390x" 978 1250 ], ··· 986 1258 } 987 1259 }, 988 1260 "node_modules/@img/sharp-libvips-linux-x64": { 989 - "version": "1.2.0", 990 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.0.tgz", 991 - "integrity": "sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg==", 1261 + "version": "1.2.3", 1262 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.3.tgz", 1263 + "integrity": "sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==", 992 1264 "cpu": [ 993 1265 "x64" 994 1266 ], ··· 1002 1274 } 1003 1275 }, 1004 1276 "node_modules/@img/sharp-libvips-linuxmusl-arm64": { 1005 - "version": "1.2.0", 1006 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.0.tgz", 1007 - "integrity": "sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q==", 1277 + "version": "1.2.3", 1278 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.3.tgz", 1279 + "integrity": "sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==", 1008 1280 "cpu": [ 1009 1281 "arm64" 1010 1282 ], ··· 1018 1290 } 1019 1291 }, 1020 1292 "node_modules/@img/sharp-libvips-linuxmusl-x64": { 1021 - "version": "1.2.0", 1022 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.0.tgz", 1023 - "integrity": "sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q==", 1293 + "version": "1.2.3", 1294 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.3.tgz", 1295 + "integrity": "sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==", 1024 1296 "cpu": [ 1025 1297 "x64" 1026 1298 ], ··· 1034 1306 } 1035 1307 }, 1036 1308 "node_modules/@img/sharp-linux-arm": { 1037 - "version": "0.34.3", 1038 - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.3.tgz", 1039 - "integrity": "sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A==", 1309 + "version": "0.34.4", 1310 + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.4.tgz", 1311 + "integrity": "sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==", 1040 1312 "cpu": [ 1041 1313 "arm" 1042 1314 ], ··· 1052 1324 "url": "https://opencollective.com/libvips" 1053 1325 }, 1054 1326 "optionalDependencies": { 1055 - "@img/sharp-libvips-linux-arm": "1.2.0" 1327 + "@img/sharp-libvips-linux-arm": "1.2.3" 1056 1328 } 1057 1329 }, 1058 1330 "node_modules/@img/sharp-linux-arm64": { 1059 - "version": "0.34.3", 1060 - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.3.tgz", 1061 - "integrity": "sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA==", 1331 + "version": "0.34.4", 1332 + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.4.tgz", 1333 + "integrity": "sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==", 1062 1334 "cpu": [ 1063 1335 "arm64" 1064 1336 ], ··· 1074 1346 "url": "https://opencollective.com/libvips" 1075 1347 }, 1076 1348 "optionalDependencies": { 1077 - "@img/sharp-libvips-linux-arm64": "1.2.0" 1349 + "@img/sharp-libvips-linux-arm64": "1.2.3" 1078 1350 } 1079 1351 }, 1080 1352 "node_modules/@img/sharp-linux-ppc64": { 1081 - "version": "0.34.3", 1082 - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.3.tgz", 1083 - "integrity": "sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA==", 1353 + "version": "0.34.4", 1354 + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.4.tgz", 1355 + "integrity": "sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==", 1084 1356 "cpu": [ 1085 1357 "ppc64" 1086 1358 ], ··· 1096 1368 "url": "https://opencollective.com/libvips" 1097 1369 }, 1098 1370 "optionalDependencies": { 1099 - "@img/sharp-libvips-linux-ppc64": "1.2.0" 1371 + "@img/sharp-libvips-linux-ppc64": "1.2.3" 1100 1372 } 1101 1373 }, 1102 1374 "node_modules/@img/sharp-linux-s390x": { 1103 - "version": "0.34.3", 1104 - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.3.tgz", 1105 - "integrity": "sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ==", 1375 + "version": "0.34.4", 1376 + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.4.tgz", 1377 + "integrity": "sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==", 1106 1378 "cpu": [ 1107 1379 "s390x" 1108 1380 ], ··· 1118 1390 "url": "https://opencollective.com/libvips" 1119 1391 }, 1120 1392 "optionalDependencies": { 1121 - "@img/sharp-libvips-linux-s390x": "1.2.0" 1393 + "@img/sharp-libvips-linux-s390x": "1.2.3" 1122 1394 } 1123 1395 }, 1124 1396 "node_modules/@img/sharp-linux-x64": { 1125 - "version": "0.34.3", 1126 - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.3.tgz", 1127 - "integrity": "sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ==", 1397 + "version": "0.34.4", 1398 + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.4.tgz", 1399 + "integrity": "sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==", 1128 1400 "cpu": [ 1129 1401 "x64" 1130 1402 ], ··· 1140 1412 "url": "https://opencollective.com/libvips" 1141 1413 }, 1142 1414 "optionalDependencies": { 1143 - "@img/sharp-libvips-linux-x64": "1.2.0" 1415 + "@img/sharp-libvips-linux-x64": "1.2.3" 1144 1416 } 1145 1417 }, 1146 1418 "node_modules/@img/sharp-linuxmusl-arm64": { 1147 - "version": "0.34.3", 1148 - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.3.tgz", 1149 - "integrity": "sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ==", 1419 + "version": "0.34.4", 1420 + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.4.tgz", 1421 + "integrity": "sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==", 1150 1422 "cpu": [ 1151 1423 "arm64" 1152 1424 ], ··· 1162 1434 "url": "https://opencollective.com/libvips" 1163 1435 }, 1164 1436 "optionalDependencies": { 1165 - "@img/sharp-libvips-linuxmusl-arm64": "1.2.0" 1437 + "@img/sharp-libvips-linuxmusl-arm64": "1.2.3" 1166 1438 } 1167 1439 }, 1168 1440 "node_modules/@img/sharp-linuxmusl-x64": { 1169 - "version": "0.34.3", 1170 - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.3.tgz", 1171 - "integrity": "sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ==", 1441 + "version": "0.34.4", 1442 + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.4.tgz", 1443 + "integrity": "sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==", 1172 1444 "cpu": [ 1173 1445 "x64" 1174 1446 ], ··· 1184 1456 "url": "https://opencollective.com/libvips" 1185 1457 }, 1186 1458 "optionalDependencies": { 1187 - "@img/sharp-libvips-linuxmusl-x64": "1.2.0" 1459 + "@img/sharp-libvips-linuxmusl-x64": "1.2.3" 1188 1460 } 1189 1461 }, 1190 1462 "node_modules/@img/sharp-wasm32": { 1191 - "version": "0.34.3", 1192 - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.3.tgz", 1193 - "integrity": "sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg==", 1463 + "version": "0.34.4", 1464 + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.4.tgz", 1465 + "integrity": "sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==", 1194 1466 "cpu": [ 1195 1467 "wasm32" 1196 1468 ], 1197 1469 "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", 1198 1470 "optional": true, 1199 1471 "dependencies": { 1200 - "@emnapi/runtime": "^1.4.4" 1472 + "@emnapi/runtime": "^1.5.0" 1201 1473 }, 1202 1474 "engines": { 1203 1475 "node": "^18.17.0 || ^20.3.0 || >=21.0.0" ··· 1207 1479 } 1208 1480 }, 1209 1481 "node_modules/@img/sharp-win32-arm64": { 1210 - "version": "0.34.3", 1211 - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.3.tgz", 1212 - "integrity": "sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ==", 1482 + "version": "0.34.4", 1483 + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.4.tgz", 1484 + "integrity": "sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==", 1213 1485 "cpu": [ 1214 1486 "arm64" 1215 1487 ], ··· 1226 1498 } 1227 1499 }, 1228 1500 "node_modules/@img/sharp-win32-ia32": { 1229 - "version": "0.34.3", 1230 - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.3.tgz", 1231 - "integrity": "sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw==", 1501 + "version": "0.34.4", 1502 + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.4.tgz", 1503 + "integrity": "sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==", 1232 1504 "cpu": [ 1233 1505 "ia32" 1234 1506 ], ··· 1245 1517 } 1246 1518 }, 1247 1519 "node_modules/@img/sharp-win32-x64": { 1248 - "version": "0.34.3", 1249 - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.3.tgz", 1250 - "integrity": "sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g==", 1520 + "version": "0.34.4", 1521 + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.4.tgz", 1522 + "integrity": "sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig==", 1251 1523 "cpu": [ 1252 1524 "x64" 1253 1525 ], ··· 1263 1535 "url": "https://opencollective.com/libvips" 1264 1536 } 1265 1537 }, 1266 - "node_modules/@isaacs/fs-minipass": { 1267 - "version": "4.0.1", 1268 - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", 1269 - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", 1270 - "dev": true, 1271 - "license": "ISC", 1272 - "dependencies": { 1273 - "minipass": "^7.0.4" 1274 - }, 1275 - "engines": { 1276 - "node": ">=18.0.0" 1277 - } 1278 - }, 1279 1538 "node_modules/@jridgewell/gen-mapping": { 1280 1539 "version": "0.3.13", 1281 1540 "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", ··· 1284 1543 "license": "MIT", 1285 1544 "dependencies": { 1286 1545 "@jridgewell/sourcemap-codec": "^1.5.0", 1546 + "@jridgewell/trace-mapping": "^0.3.24" 1547 + } 1548 + }, 1549 + "node_modules/@jridgewell/remapping": { 1550 + "version": "2.3.5", 1551 + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", 1552 + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", 1553 + "dev": true, 1554 + "license": "MIT", 1555 + "dependencies": { 1556 + "@jridgewell/gen-mapping": "^0.3.5", 1287 1557 "@jridgewell/trace-mapping": "^0.3.24" 1288 1558 } 1289 1559 }, ··· 1335 1605 } 1336 1606 }, 1337 1607 "node_modules/@next/env": { 1338 - "version": "15.4.6", 1339 - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.4.6.tgz", 1340 - "integrity": "sha512-yHDKVTcHrZy/8TWhj0B23ylKv5ypocuCwey9ZqPyv4rPdUdRzpGCkSi03t04KBPyU96kxVtUqx6O3nE1kpxASQ==", 1608 + "version": "16.0.1", 1609 + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.1.tgz", 1610 + "integrity": "sha512-LFvlK0TG2L3fEOX77OC35KowL8D7DlFF45C0OvKMC4hy8c/md1RC4UMNDlUGJqfCoCS2VWrZ4dSE6OjaX5+8mw==", 1341 1611 "license": "MIT" 1342 1612 }, 1343 1613 "node_modules/@next/eslint-plugin-next": { 1344 - "version": "15.4.6", 1345 - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.4.6.tgz", 1346 - "integrity": "sha512-2NOu3ln+BTcpnbIDuxx6MNq+pRrCyey4WSXGaJIyt0D2TYicHeO9QrUENNjcf673n3B1s7hsiV5xBYRCK1Q8kA==", 1614 + "version": "16.0.1", 1615 + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.0.1.tgz", 1616 + "integrity": "sha512-g4Cqmv/gyFEXNeVB2HkqDlYKfy+YrlM2k8AVIO/YQVEPfhVruH1VA99uT1zELLnPLIeOnx8IZ6Ddso0asfTIdw==", 1347 1617 "dev": true, 1348 1618 "license": "MIT", 1349 1619 "dependencies": { ··· 1351 1621 } 1352 1622 }, 1353 1623 "node_modules/@next/swc-darwin-arm64": { 1354 - "version": "15.4.6", 1355 - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.4.6.tgz", 1356 - "integrity": "sha512-667R0RTP4DwxzmrqTs4Lr5dcEda9OxuZsVFsjVtxVMVhzSpo6nLclXejJVfQo2/g7/Z9qF3ETDmN3h65mTjpTQ==", 1624 + "version": "16.0.1", 1625 + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.0.1.tgz", 1626 + "integrity": "sha512-R0YxRp6/4W7yG1nKbfu41bp3d96a0EalonQXiMe+1H9GTHfKxGNCGFNWUho18avRBPsO8T3RmdWuzmfurlQPbg==", 1357 1627 "cpu": [ 1358 1628 "arm64" 1359 1629 ], ··· 1367 1637 } 1368 1638 }, 1369 1639 "node_modules/@next/swc-darwin-x64": { 1370 - "version": "15.4.6", 1371 - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.4.6.tgz", 1372 - "integrity": "sha512-KMSFoistFkaiQYVQQnaU9MPWtp/3m0kn2Xed1Ces5ll+ag1+rlac20sxG+MqhH2qYWX1O2GFOATQXEyxKiIscg==", 1640 + "version": "16.0.1", 1641 + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.0.1.tgz", 1642 + "integrity": "sha512-kETZBocRux3xITiZtOtVoVvXyQLB7VBxN7L6EPqgI5paZiUlnsgYv4q8diTNYeHmF9EiehydOBo20lTttCbHAg==", 1373 1643 "cpu": [ 1374 1644 "x64" 1375 1645 ], ··· 1383 1653 } 1384 1654 }, 1385 1655 "node_modules/@next/swc-linux-arm64-gnu": { 1386 - "version": "15.4.6", 1387 - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.4.6.tgz", 1388 - "integrity": "sha512-PnOx1YdO0W7m/HWFeYd2A6JtBO8O8Eb9h6nfJia2Dw1sRHoHpNf6lN1U4GKFRzRDBi9Nq2GrHk9PF3Vmwf7XVw==", 1656 + "version": "16.0.1", 1657 + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.0.1.tgz", 1658 + "integrity": "sha512-hWg3BtsxQuSKhfe0LunJoqxjO4NEpBmKkE+P2Sroos7yB//OOX3jD5ISP2wv8QdUwtRehMdwYz6VB50mY6hqAg==", 1389 1659 "cpu": [ 1390 1660 "arm64" 1391 1661 ], ··· 1399 1669 } 1400 1670 }, 1401 1671 "node_modules/@next/swc-linux-arm64-musl": { 1402 - "version": "15.4.6", 1403 - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.4.6.tgz", 1404 - "integrity": "sha512-XBbuQddtY1p5FGPc2naMO0kqs4YYtLYK/8aPausI5lyOjr4J77KTG9mtlU4P3NwkLI1+OjsPzKVvSJdMs3cFaw==", 1672 + "version": "16.0.1", 1673 + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.0.1.tgz", 1674 + "integrity": "sha512-UPnOvYg+fjAhP3b1iQStcYPWeBFRLrugEyK/lDKGk7kLNua8t5/DvDbAEFotfV1YfcOY6bru76qN9qnjLoyHCQ==", 1405 1675 "cpu": [ 1406 1676 "arm64" 1407 1677 ], ··· 1415 1685 } 1416 1686 }, 1417 1687 "node_modules/@next/swc-linux-x64-gnu": { 1418 - "version": "15.4.6", 1419 - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.4.6.tgz", 1420 - "integrity": "sha512-+WTeK7Qdw82ez3U9JgD+igBAP75gqZ1vbK6R8PlEEuY0OIe5FuYXA4aTjL811kWPf7hNeslD4hHK2WoM9W0IgA==", 1688 + "version": "16.0.1", 1689 + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.0.1.tgz", 1690 + "integrity": "sha512-Et81SdWkcRqAJziIgFtsFyJizHoWne4fzJkvjd6V4wEkWTB4MX6J0uByUb0peiJQ4WeAt6GGmMszE5KrXK6WKg==", 1421 1691 "cpu": [ 1422 1692 "x64" 1423 1693 ], ··· 1431 1701 } 1432 1702 }, 1433 1703 "node_modules/@next/swc-linux-x64-musl": { 1434 - "version": "15.4.6", 1435 - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.4.6.tgz", 1436 - "integrity": "sha512-XP824mCbgQsK20jlXKrUpZoh/iO3vUWhMpxCz8oYeagoiZ4V0TQiKy0ASji1KK6IAe3DYGfj5RfKP6+L2020OQ==", 1704 + "version": "16.0.1", 1705 + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.0.1.tgz", 1706 + "integrity": "sha512-qBbgYEBRrC1egcG03FZaVfVxrJm8wBl7vr8UFKplnxNRprctdP26xEv9nJ07Ggq4y1adwa0nz2mz83CELY7N6Q==", 1437 1707 "cpu": [ 1438 1708 "x64" 1439 1709 ], ··· 1447 1717 } 1448 1718 }, 1449 1719 "node_modules/@next/swc-win32-arm64-msvc": { 1450 - "version": "15.4.6", 1451 - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.4.6.tgz", 1452 - "integrity": "sha512-FxrsenhUz0LbgRkNWx6FRRJIPe/MI1JRA4W4EPd5leXO00AZ6YU8v5vfx4MDXTvN77lM/EqsE3+6d2CIeF5NYg==", 1720 + "version": "16.0.1", 1721 + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.0.1.tgz", 1722 + "integrity": "sha512-cPuBjYP6I699/RdbHJonb3BiRNEDm5CKEBuJ6SD8k3oLam2fDRMKAvmrli4QMDgT2ixyRJ0+DTkiODbIQhRkeQ==", 1453 1723 "cpu": [ 1454 1724 "arm64" 1455 1725 ], ··· 1463 1733 } 1464 1734 }, 1465 1735 "node_modules/@next/swc-win32-x64-msvc": { 1466 - "version": "15.4.6", 1467 - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.4.6.tgz", 1468 - "integrity": "sha512-T4ufqnZ4u88ZheczkBTtOF+eKaM14V8kbjud/XrAakoM5DKQWjW09vD6B9fsdsWS2T7D5EY31hRHdta7QKWOng==", 1736 + "version": "16.0.1", 1737 + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.0.1.tgz", 1738 + "integrity": "sha512-XeEUJsE4JYtfrXe/LaJn3z1pD19fK0Q6Er8Qoufi+HqvdO4LEPyCxLUt4rxA+4RfYo6S9gMlmzCMU2F+AatFqQ==", 1469 1739 "cpu": [ 1470 1740 "x64" 1471 1741 ], ··· 1533 1803 "dev": true, 1534 1804 "license": "MIT" 1535 1805 }, 1536 - "node_modules/@rushstack/eslint-patch": { 1537 - "version": "1.12.0", 1538 - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.12.0.tgz", 1539 - "integrity": "sha512-5EwMtOqvJMMa3HbmxLlF74e+3/HhwBTMcvt3nqVJgGCozO6hzIPOBlwm8mGVNR9SN2IJpxSnlxczyDjcn7qIyw==", 1540 - "dev": true, 1541 - "license": "MIT" 1542 - }, 1543 1806 "node_modules/@swc/helpers": { 1544 1807 "version": "0.5.15", 1545 1808 "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", ··· 1550 1813 } 1551 1814 }, 1552 1815 "node_modules/@tailwindcss/node": { 1553 - "version": "4.1.11", 1554 - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.11.tgz", 1555 - "integrity": "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==", 1816 + "version": "4.1.16", 1817 + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.16.tgz", 1818 + "integrity": "sha512-BX5iaSsloNuvKNHRN3k2RcCuTEgASTo77mofW0vmeHkfrDWaoFAFvNHpEgtu0eqyypcyiBkDWzSMxJhp3AUVcw==", 1556 1819 "dev": true, 1557 1820 "license": "MIT", 1558 1821 "dependencies": { 1559 - "@ampproject/remapping": "^2.3.0", 1560 - "enhanced-resolve": "^5.18.1", 1561 - "jiti": "^2.4.2", 1562 - "lightningcss": "1.30.1", 1563 - "magic-string": "^0.30.17", 1822 + "@jridgewell/remapping": "^2.3.4", 1823 + "enhanced-resolve": "^5.18.3", 1824 + "jiti": "^2.6.1", 1825 + "lightningcss": "1.30.2", 1826 + "magic-string": "^0.30.19", 1564 1827 "source-map-js": "^1.2.1", 1565 - "tailwindcss": "4.1.11" 1828 + "tailwindcss": "4.1.16" 1566 1829 } 1567 1830 }, 1568 1831 "node_modules/@tailwindcss/oxide": { 1569 - "version": "4.1.11", 1570 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.11.tgz", 1571 - "integrity": "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg==", 1832 + "version": "4.1.16", 1833 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.16.tgz", 1834 + "integrity": "sha512-2OSv52FRuhdlgyOQqgtQHuCgXnS8nFSYRp2tJ+4WZXKgTxqPy7SMSls8c3mPT5pkZ17SBToGM5LHEJBO7miEdg==", 1572 1835 "dev": true, 1573 - "hasInstallScript": true, 1574 1836 "license": "MIT", 1575 - "dependencies": { 1576 - "detect-libc": "^2.0.4", 1577 - "tar": "^7.4.3" 1578 - }, 1579 1837 "engines": { 1580 1838 "node": ">= 10" 1581 1839 }, 1582 1840 "optionalDependencies": { 1583 - "@tailwindcss/oxide-android-arm64": "4.1.11", 1584 - "@tailwindcss/oxide-darwin-arm64": "4.1.11", 1585 - "@tailwindcss/oxide-darwin-x64": "4.1.11", 1586 - "@tailwindcss/oxide-freebsd-x64": "4.1.11", 1587 - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11", 1588 - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11", 1589 - "@tailwindcss/oxide-linux-arm64-musl": "4.1.11", 1590 - "@tailwindcss/oxide-linux-x64-gnu": "4.1.11", 1591 - "@tailwindcss/oxide-linux-x64-musl": "4.1.11", 1592 - "@tailwindcss/oxide-wasm32-wasi": "4.1.11", 1593 - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11", 1594 - "@tailwindcss/oxide-win32-x64-msvc": "4.1.11" 1841 + "@tailwindcss/oxide-android-arm64": "4.1.16", 1842 + "@tailwindcss/oxide-darwin-arm64": "4.1.16", 1843 + "@tailwindcss/oxide-darwin-x64": "4.1.16", 1844 + "@tailwindcss/oxide-freebsd-x64": "4.1.16", 1845 + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.16", 1846 + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.16", 1847 + "@tailwindcss/oxide-linux-arm64-musl": "4.1.16", 1848 + "@tailwindcss/oxide-linux-x64-gnu": "4.1.16", 1849 + "@tailwindcss/oxide-linux-x64-musl": "4.1.16", 1850 + "@tailwindcss/oxide-wasm32-wasi": "4.1.16", 1851 + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.16", 1852 + "@tailwindcss/oxide-win32-x64-msvc": "4.1.16" 1595 1853 } 1596 1854 }, 1597 1855 "node_modules/@tailwindcss/oxide-android-arm64": { 1598 - "version": "4.1.11", 1599 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.11.tgz", 1600 - "integrity": "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg==", 1856 + "version": "4.1.16", 1857 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.16.tgz", 1858 + "integrity": "sha512-8+ctzkjHgwDJ5caq9IqRSgsP70xhdhJvm+oueS/yhD5ixLhqTw9fSL1OurzMUhBwE5zK26FXLCz2f/RtkISqHA==", 1601 1859 "cpu": [ 1602 1860 "arm64" 1603 1861 ], ··· 1612 1870 } 1613 1871 }, 1614 1872 "node_modules/@tailwindcss/oxide-darwin-arm64": { 1615 - "version": "4.1.11", 1616 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.11.tgz", 1617 - "integrity": "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ==", 1873 + "version": "4.1.16", 1874 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.16.tgz", 1875 + "integrity": "sha512-C3oZy5042v2FOALBZtY0JTDnGNdS6w7DxL/odvSny17ORUnaRKhyTse8xYi3yKGyfnTUOdavRCdmc8QqJYwFKA==", 1618 1876 "cpu": [ 1619 1877 "arm64" 1620 1878 ], ··· 1629 1887 } 1630 1888 }, 1631 1889 "node_modules/@tailwindcss/oxide-darwin-x64": { 1632 - "version": "4.1.11", 1633 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.11.tgz", 1634 - "integrity": "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw==", 1890 + "version": "4.1.16", 1891 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.16.tgz", 1892 + "integrity": "sha512-vjrl/1Ub9+JwU6BP0emgipGjowzYZMjbWCDqwA2Z4vCa+HBSpP4v6U2ddejcHsolsYxwL5r4bPNoamlV0xDdLg==", 1635 1893 "cpu": [ 1636 1894 "x64" 1637 1895 ], ··· 1646 1904 } 1647 1905 }, 1648 1906 "node_modules/@tailwindcss/oxide-freebsd-x64": { 1649 - "version": "4.1.11", 1650 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.11.tgz", 1651 - "integrity": "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA==", 1907 + "version": "4.1.16", 1908 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.16.tgz", 1909 + "integrity": "sha512-TSMpPYpQLm+aR1wW5rKuUuEruc/oOX3C7H0BTnPDn7W/eMw8W+MRMpiypKMkXZfwH8wqPIRKppuZoedTtNj2tg==", 1652 1910 "cpu": [ 1653 1911 "x64" 1654 1912 ], ··· 1663 1921 } 1664 1922 }, 1665 1923 "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { 1666 - "version": "4.1.11", 1667 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.11.tgz", 1668 - "integrity": "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg==", 1924 + "version": "4.1.16", 1925 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.16.tgz", 1926 + "integrity": "sha512-p0GGfRg/w0sdsFKBjMYvvKIiKy/LNWLWgV/plR4lUgrsxFAoQBFrXkZ4C0w8IOXfslB9vHK/JGASWD2IefIpvw==", 1669 1927 "cpu": [ 1670 1928 "arm" 1671 1929 ], ··· 1680 1938 } 1681 1939 }, 1682 1940 "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { 1683 - "version": "4.1.11", 1684 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.11.tgz", 1685 - "integrity": "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ==", 1941 + "version": "4.1.16", 1942 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.16.tgz", 1943 + "integrity": "sha512-DoixyMmTNO19rwRPdqviTrG1rYzpxgyYJl8RgQvdAQUzxC1ToLRqtNJpU/ATURSKgIg6uerPw2feW0aS8SNr/w==", 1686 1944 "cpu": [ 1687 1945 "arm64" 1688 1946 ], ··· 1697 1955 } 1698 1956 }, 1699 1957 "node_modules/@tailwindcss/oxide-linux-arm64-musl": { 1700 - "version": "4.1.11", 1701 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.11.tgz", 1702 - "integrity": "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ==", 1958 + "version": "4.1.16", 1959 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.16.tgz", 1960 + "integrity": "sha512-H81UXMa9hJhWhaAUca6bU2wm5RRFpuHImrwXBUvPbYb+3jo32I9VIwpOX6hms0fPmA6f2pGVlybO6qU8pF4fzQ==", 1703 1961 "cpu": [ 1704 1962 "arm64" 1705 1963 ], ··· 1714 1972 } 1715 1973 }, 1716 1974 "node_modules/@tailwindcss/oxide-linux-x64-gnu": { 1717 - "version": "4.1.11", 1718 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.11.tgz", 1719 - "integrity": "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg==", 1975 + "version": "4.1.16", 1976 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.16.tgz", 1977 + "integrity": "sha512-ZGHQxDtFC2/ruo7t99Qo2TTIvOERULPl5l0K1g0oK6b5PGqjYMga+FcY1wIUnrUxY56h28FxybtDEla+ICOyew==", 1720 1978 "cpu": [ 1721 1979 "x64" 1722 1980 ], ··· 1731 1989 } 1732 1990 }, 1733 1991 "node_modules/@tailwindcss/oxide-linux-x64-musl": { 1734 - "version": "4.1.11", 1735 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.11.tgz", 1736 - "integrity": "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q==", 1992 + "version": "4.1.16", 1993 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.16.tgz", 1994 + "integrity": "sha512-Oi1tAaa0rcKf1Og9MzKeINZzMLPbhxvm7rno5/zuP1WYmpiG0bEHq4AcRUiG2165/WUzvxkW4XDYCscZWbTLZw==", 1737 1995 "cpu": [ 1738 1996 "x64" 1739 1997 ], ··· 1748 2006 } 1749 2007 }, 1750 2008 "node_modules/@tailwindcss/oxide-wasm32-wasi": { 1751 - "version": "4.1.11", 1752 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.11.tgz", 1753 - "integrity": "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g==", 2009 + "version": "4.1.16", 2010 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.16.tgz", 2011 + "integrity": "sha512-B01u/b8LteGRwucIBmCQ07FVXLzImWESAIMcUU6nvFt/tYsQ6IHz8DmZ5KtvmwxD+iTYBtM1xwoGXswnlu9v0Q==", 1754 2012 "bundleDependencies": [ 1755 2013 "@napi-rs/wasm-runtime", 1756 2014 "@emnapi/core", ··· 1766 2024 "license": "MIT", 1767 2025 "optional": true, 1768 2026 "dependencies": { 1769 - "@emnapi/core": "^1.4.3", 1770 - "@emnapi/runtime": "^1.4.3", 1771 - "@emnapi/wasi-threads": "^1.0.2", 1772 - "@napi-rs/wasm-runtime": "^0.2.11", 1773 - "@tybys/wasm-util": "^0.9.0", 1774 - "tslib": "^2.8.0" 2027 + "@emnapi/core": "^1.5.0", 2028 + "@emnapi/runtime": "^1.5.0", 2029 + "@emnapi/wasi-threads": "^1.1.0", 2030 + "@napi-rs/wasm-runtime": "^1.0.7", 2031 + "@tybys/wasm-util": "^0.10.1", 2032 + "tslib": "^2.4.0" 1775 2033 }, 1776 2034 "engines": { 1777 2035 "node": ">=14.0.0" 1778 2036 } 1779 2037 }, 1780 2038 "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { 1781 - "version": "4.1.11", 1782 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz", 1783 - "integrity": "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w==", 2039 + "version": "4.1.16", 2040 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.16.tgz", 2041 + "integrity": "sha512-zX+Q8sSkGj6HKRTMJXuPvOcP8XfYON24zJBRPlszcH1Np7xuHXhWn8qfFjIujVzvH3BHU+16jBXwgpl20i+v9A==", 1784 2042 "cpu": [ 1785 2043 "arm64" 1786 2044 ], ··· 1795 2053 } 1796 2054 }, 1797 2055 "node_modules/@tailwindcss/oxide-win32-x64-msvc": { 1798 - "version": "4.1.11", 1799 - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.11.tgz", 1800 - "integrity": "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg==", 2056 + "version": "4.1.16", 2057 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.16.tgz", 2058 + "integrity": "sha512-m5dDFJUEejbFqP+UXVstd4W/wnxA4F61q8SoL+mqTypId2T2ZpuxosNSgowiCnLp2+Z+rivdU0AqpfgiD7yCBg==", 1801 2059 "cpu": [ 1802 2060 "x64" 1803 2061 ], ··· 1812 2070 } 1813 2071 }, 1814 2072 "node_modules/@tailwindcss/postcss": { 1815 - "version": "4.1.11", 1816 - "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.11.tgz", 1817 - "integrity": "sha512-q/EAIIpF6WpLhKEuQSEVMZNMIY8KhWoAemZ9eylNAih9jxMGAYPPWBn3I9QL/2jZ+e7OEz/tZkX5HwbBR4HohA==", 2073 + "version": "4.1.16", 2074 + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.16.tgz", 2075 + "integrity": "sha512-Qn3SFGPXYQMKR/UtqS+dqvPrzEeBZHrFA92maT4zijCVggdsXnDBMsPFJo1eArX3J+O+Gi+8pV4PkqjLCNBk3A==", 1818 2076 "dev": true, 1819 2077 "license": "MIT", 1820 2078 "dependencies": { 1821 2079 "@alloc/quick-lru": "^5.2.0", 1822 - "@tailwindcss/node": "4.1.11", 1823 - "@tailwindcss/oxide": "4.1.11", 2080 + "@tailwindcss/node": "4.1.16", 2081 + "@tailwindcss/oxide": "4.1.16", 1824 2082 "postcss": "^8.4.41", 1825 - "tailwindcss": "4.1.11" 2083 + "tailwindcss": "4.1.16" 1826 2084 } 1827 2085 }, 1828 2086 "node_modules/@tybys/wasm-util": { ··· 1864 2122 "license": "MIT" 1865 2123 }, 1866 2124 "node_modules/@types/node": { 1867 - "version": "24.2.1", 1868 - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.2.1.tgz", 1869 - "integrity": "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ==", 2125 + "version": "24.9.2", 2126 + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.2.tgz", 2127 + "integrity": "sha512-uWN8YqxXxqFMX2RqGOrumsKeti4LlmIMIyV0lgut4jx7KQBcBiW6vkDtIBvHnHIquwNfJhk8v2OtmO8zXWHfPA==", 1870 2128 "dev": true, 1871 2129 "license": "MIT", 1872 2130 "dependencies": { 1873 - "undici-types": "~7.10.0" 2131 + "undici-types": "~7.16.0" 1874 2132 } 1875 2133 }, 1876 2134 "node_modules/@types/react": { 1877 - "version": "19.1.10", 1878 - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.10.tgz", 1879 - "integrity": "sha512-EhBeSYX0Y6ye8pNebpKrwFJq7BoQ8J5SO6NlvNwwHjSj6adXJViPQrKlsyPw7hLBLvckEMO1yxeGdR82YBBlDg==", 2135 + "version": "19.2.2", 2136 + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", 2137 + "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", 1880 2138 "dev": true, 1881 2139 "license": "MIT", 1882 2140 "dependencies": { ··· 1884 2142 } 1885 2143 }, 1886 2144 "node_modules/@types/react-dom": { 1887 - "version": "19.1.7", 1888 - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.7.tgz", 1889 - "integrity": "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw==", 2145 + "version": "19.2.2", 2146 + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.2.tgz", 2147 + "integrity": "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==", 1890 2148 "dev": true, 1891 2149 "license": "MIT", 1892 2150 "peerDependencies": { 1893 - "@types/react": "^19.0.0" 2151 + "@types/react": "^19.2.0" 1894 2152 } 1895 2153 }, 1896 2154 "node_modules/@typescript-eslint/eslint-plugin": { 1897 - "version": "8.39.1", 1898 - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.39.1.tgz", 1899 - "integrity": "sha512-yYegZ5n3Yr6eOcqgj2nJH8cH/ZZgF+l0YIdKILSDjYFRjgYQMgv/lRjV5Z7Up04b9VYUondt8EPMqg7kTWgJ2g==", 2155 + "version": "8.46.2", 2156 + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.2.tgz", 2157 + "integrity": "sha512-ZGBMToy857/NIPaaCucIUQgqueOiq7HeAKkhlvqVV4lm089zUFW6ikRySx2v+cAhKeUCPuWVHeimyk6Dw1iY3w==", 1900 2158 "dev": true, 1901 2159 "license": "MIT", 1902 2160 "dependencies": { 1903 2161 "@eslint-community/regexpp": "^4.10.0", 1904 - "@typescript-eslint/scope-manager": "8.39.1", 1905 - "@typescript-eslint/type-utils": "8.39.1", 1906 - "@typescript-eslint/utils": "8.39.1", 1907 - "@typescript-eslint/visitor-keys": "8.39.1", 2162 + "@typescript-eslint/scope-manager": "8.46.2", 2163 + "@typescript-eslint/type-utils": "8.46.2", 2164 + "@typescript-eslint/utils": "8.46.2", 2165 + "@typescript-eslint/visitor-keys": "8.46.2", 1908 2166 "graphemer": "^1.4.0", 1909 2167 "ignore": "^7.0.0", 1910 2168 "natural-compare": "^1.4.0", ··· 1918 2176 "url": "https://opencollective.com/typescript-eslint" 1919 2177 }, 1920 2178 "peerDependencies": { 1921 - "@typescript-eslint/parser": "^8.39.1", 2179 + "@typescript-eslint/parser": "^8.46.2", 1922 2180 "eslint": "^8.57.0 || ^9.0.0", 1923 2181 "typescript": ">=4.8.4 <6.0.0" 1924 2182 } ··· 1934 2192 } 1935 2193 }, 1936 2194 "node_modules/@typescript-eslint/parser": { 1937 - "version": "8.39.1", 1938 - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.39.1.tgz", 1939 - "integrity": "sha512-pUXGCuHnnKw6PyYq93lLRiZm3vjuslIy7tus1lIQTYVK9bL8XBgJnCWm8a0KcTtHC84Yya1Q6rtll+duSMj0dg==", 2195 + "version": "8.46.2", 2196 + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.2.tgz", 2197 + "integrity": "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==", 1940 2198 "dev": true, 1941 2199 "license": "MIT", 1942 2200 "dependencies": { 1943 - "@typescript-eslint/scope-manager": "8.39.1", 1944 - "@typescript-eslint/types": "8.39.1", 1945 - "@typescript-eslint/typescript-estree": "8.39.1", 1946 - "@typescript-eslint/visitor-keys": "8.39.1", 2201 + "@typescript-eslint/scope-manager": "8.46.2", 2202 + "@typescript-eslint/types": "8.46.2", 2203 + "@typescript-eslint/typescript-estree": "8.46.2", 2204 + "@typescript-eslint/visitor-keys": "8.46.2", 1947 2205 "debug": "^4.3.4" 1948 2206 }, 1949 2207 "engines": { ··· 1959 2217 } 1960 2218 }, 1961 2219 "node_modules/@typescript-eslint/project-service": { 1962 - "version": "8.39.1", 1963 - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.39.1.tgz", 1964 - "integrity": "sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw==", 2220 + "version": "8.46.2", 2221 + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.2.tgz", 2222 + "integrity": "sha512-PULOLZ9iqwI7hXcmL4fVfIsBi6AN9YxRc0frbvmg8f+4hQAjQ5GYNKK0DIArNo+rOKmR/iBYwkpBmnIwin4wBg==", 1965 2223 "dev": true, 1966 2224 "license": "MIT", 1967 2225 "dependencies": { 1968 - "@typescript-eslint/tsconfig-utils": "^8.39.1", 1969 - "@typescript-eslint/types": "^8.39.1", 2226 + "@typescript-eslint/tsconfig-utils": "^8.46.2", 2227 + "@typescript-eslint/types": "^8.46.2", 1970 2228 "debug": "^4.3.4" 1971 2229 }, 1972 2230 "engines": { ··· 1981 2239 } 1982 2240 }, 1983 2241 "node_modules/@typescript-eslint/scope-manager": { 1984 - "version": "8.39.1", 1985 - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.39.1.tgz", 1986 - "integrity": "sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw==", 2242 + "version": "8.46.2", 2243 + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.2.tgz", 2244 + "integrity": "sha512-LF4b/NmGvdWEHD2H4MsHD8ny6JpiVNDzrSZr3CsckEgCbAGZbYM4Cqxvi9L+WqDMT+51Ozy7lt2M+d0JLEuBqA==", 1987 2245 "dev": true, 1988 2246 "license": "MIT", 1989 2247 "dependencies": { 1990 - "@typescript-eslint/types": "8.39.1", 1991 - "@typescript-eslint/visitor-keys": "8.39.1" 2248 + "@typescript-eslint/types": "8.46.2", 2249 + "@typescript-eslint/visitor-keys": "8.46.2" 1992 2250 }, 1993 2251 "engines": { 1994 2252 "node": "^18.18.0 || ^20.9.0 || >=21.1.0" ··· 1999 2257 } 2000 2258 }, 2001 2259 "node_modules/@typescript-eslint/tsconfig-utils": { 2002 - "version": "8.39.1", 2003 - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.1.tgz", 2004 - "integrity": "sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA==", 2260 + "version": "8.46.2", 2261 + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.2.tgz", 2262 + "integrity": "sha512-a7QH6fw4S57+F5y2FIxxSDyi5M4UfGF+Jl1bCGd7+L4KsaUY80GsiF/t0UoRFDHAguKlBaACWJRmdrc6Xfkkag==", 2005 2263 "dev": true, 2006 2264 "license": "MIT", 2007 2265 "engines": { ··· 2016 2274 } 2017 2275 }, 2018 2276 "node_modules/@typescript-eslint/type-utils": { 2019 - "version": "8.39.1", 2020 - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.39.1.tgz", 2021 - "integrity": "sha512-gu9/ahyatyAdQbKeHnhT4R+y3YLtqqHyvkfDxaBYk97EcbfChSJXyaJnIL3ygUv7OuZatePHmQvuH5ru0lnVeA==", 2277 + "version": "8.46.2", 2278 + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.2.tgz", 2279 + "integrity": "sha512-HbPM4LbaAAt/DjxXaG9yiS9brOOz6fabal4uvUmaUYe6l3K1phQDMQKBRUrr06BQkxkvIZVVHttqiybM9nJsLA==", 2022 2280 "dev": true, 2023 2281 "license": "MIT", 2024 2282 "dependencies": { 2025 - "@typescript-eslint/types": "8.39.1", 2026 - "@typescript-eslint/typescript-estree": "8.39.1", 2027 - "@typescript-eslint/utils": "8.39.1", 2283 + "@typescript-eslint/types": "8.46.2", 2284 + "@typescript-eslint/typescript-estree": "8.46.2", 2285 + "@typescript-eslint/utils": "8.46.2", 2028 2286 "debug": "^4.3.4", 2029 2287 "ts-api-utils": "^2.1.0" 2030 2288 }, ··· 2041 2299 } 2042 2300 }, 2043 2301 "node_modules/@typescript-eslint/types": { 2044 - "version": "8.39.1", 2045 - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.1.tgz", 2046 - "integrity": "sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==", 2302 + "version": "8.46.2", 2303 + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.2.tgz", 2304 + "integrity": "sha512-lNCWCbq7rpg7qDsQrd3D6NyWYu+gkTENkG5IKYhUIcxSb59SQC/hEQ+MrG4sTgBVghTonNWq42bA/d4yYumldQ==", 2047 2305 "dev": true, 2048 2306 "license": "MIT", 2049 2307 "engines": { ··· 2055 2313 } 2056 2314 }, 2057 2315 "node_modules/@typescript-eslint/typescript-estree": { 2058 - "version": "8.39.1", 2059 - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.1.tgz", 2060 - "integrity": "sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw==", 2316 + "version": "8.46.2", 2317 + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.2.tgz", 2318 + "integrity": "sha512-f7rW7LJ2b7Uh2EiQ+7sza6RDZnajbNbemn54Ob6fRwQbgcIn+GWfyuHDHRYgRoZu1P4AayVScrRW+YfbTvPQoQ==", 2061 2319 "dev": true, 2062 2320 "license": "MIT", 2063 2321 "dependencies": { 2064 - "@typescript-eslint/project-service": "8.39.1", 2065 - "@typescript-eslint/tsconfig-utils": "8.39.1", 2066 - "@typescript-eslint/types": "8.39.1", 2067 - "@typescript-eslint/visitor-keys": "8.39.1", 2322 + "@typescript-eslint/project-service": "8.46.2", 2323 + "@typescript-eslint/tsconfig-utils": "8.46.2", 2324 + "@typescript-eslint/types": "8.46.2", 2325 + "@typescript-eslint/visitor-keys": "8.46.2", 2068 2326 "debug": "^4.3.4", 2069 2327 "fast-glob": "^3.3.2", 2070 2328 "is-glob": "^4.0.3", ··· 2140 2398 } 2141 2399 }, 2142 2400 "node_modules/@typescript-eslint/utils": { 2143 - "version": "8.39.1", 2144 - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.39.1.tgz", 2145 - "integrity": "sha512-VF5tZ2XnUSTuiqZFXCZfZs1cgkdd3O/sSYmdo2EpSyDlC86UM/8YytTmKnehOW3TGAlivqTDT6bS87B/GQ/jyg==", 2401 + "version": "8.46.2", 2402 + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.2.tgz", 2403 + "integrity": "sha512-sExxzucx0Tud5tE0XqR0lT0psBQvEpnpiul9XbGUB1QwpWJJAps1O/Z7hJxLGiZLBKMCutjTzDgmd1muEhBnVg==", 2146 2404 "dev": true, 2147 2405 "license": "MIT", 2148 2406 "dependencies": { 2149 2407 "@eslint-community/eslint-utils": "^4.7.0", 2150 - "@typescript-eslint/scope-manager": "8.39.1", 2151 - "@typescript-eslint/types": "8.39.1", 2152 - "@typescript-eslint/typescript-estree": "8.39.1" 2408 + "@typescript-eslint/scope-manager": "8.46.2", 2409 + "@typescript-eslint/types": "8.46.2", 2410 + "@typescript-eslint/typescript-estree": "8.46.2" 2153 2411 }, 2154 2412 "engines": { 2155 2413 "node": "^18.18.0 || ^20.9.0 || >=21.1.0" ··· 2164 2422 } 2165 2423 }, 2166 2424 "node_modules/@typescript-eslint/visitor-keys": { 2167 - "version": "8.39.1", 2168 - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.1.tgz", 2169 - "integrity": "sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A==", 2425 + "version": "8.46.2", 2426 + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.2.tgz", 2427 + "integrity": "sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w==", 2170 2428 "dev": true, 2171 2429 "license": "MIT", 2172 2430 "dependencies": { 2173 - "@typescript-eslint/types": "8.39.1", 2431 + "@typescript-eslint/types": "8.46.2", 2174 2432 "eslint-visitor-keys": "^4.2.1" 2175 2433 }, 2176 2434 "engines": { ··· 2743 3001 "dev": true, 2744 3002 "license": "MIT" 2745 3003 }, 3004 + "node_modules/baseline-browser-mapping": { 3005 + "version": "2.8.23", 3006 + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.23.tgz", 3007 + "integrity": "sha512-616V5YX4bepJFzNyOfce5Fa8fDJMfoxzOIzDCZwaGL8MKVpFrXqfNUoIpRn9YMI5pXf/VKgzjB4htFMsFKKdiQ==", 3008 + "dev": true, 3009 + "license": "Apache-2.0", 3010 + "bin": { 3011 + "baseline-browser-mapping": "dist/cli.js" 3012 + } 3013 + }, 2746 3014 "node_modules/brace-expansion": { 2747 3015 "version": "1.1.12", 2748 3016 "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", ··· 2767 3035 "node": ">=8" 2768 3036 } 2769 3037 }, 3038 + "node_modules/browserslist": { 3039 + "version": "4.27.0", 3040 + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.27.0.tgz", 3041 + "integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==", 3042 + "dev": true, 3043 + "funding": [ 3044 + { 3045 + "type": "opencollective", 3046 + "url": "https://opencollective.com/browserslist" 3047 + }, 3048 + { 3049 + "type": "tidelift", 3050 + "url": "https://tidelift.com/funding/github/npm/browserslist" 3051 + }, 3052 + { 3053 + "type": "github", 3054 + "url": "https://github.com/sponsors/ai" 3055 + } 3056 + ], 3057 + "license": "MIT", 3058 + "dependencies": { 3059 + "baseline-browser-mapping": "^2.8.19", 3060 + "caniuse-lite": "^1.0.30001751", 3061 + "electron-to-chromium": "^1.5.238", 3062 + "node-releases": "^2.0.26", 3063 + "update-browserslist-db": "^1.1.4" 3064 + }, 3065 + "bin": { 3066 + "browserslist": "cli.js" 3067 + }, 3068 + "engines": { 3069 + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" 3070 + } 3071 + }, 2770 3072 "node_modules/call-bind": { 2771 3073 "version": "1.0.8", 2772 3074 "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", ··· 2828 3130 } 2829 3131 }, 2830 3132 "node_modules/caniuse-lite": { 2831 - "version": "1.0.30001734", 2832 - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001734.tgz", 2833 - "integrity": "sha512-uhE1Ye5vgqju6OI71HTQqcBCZrvHugk0MjLak7Q+HfoBgoq5Bi+5YnwjP4fjDgrtYr/l8MVRBvzz9dPD4KyK0A==", 3133 + "version": "1.0.30001753", 3134 + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001753.tgz", 3135 + "integrity": "sha512-Bj5H35MD/ebaOV4iDLqPEtiliTN29qkGtEHCwawWn4cYm+bPJM2NsaP30vtZcnERClMzp52J4+aw2UNbK4o+zw==", 2834 3136 "funding": [ 2835 3137 { 2836 3138 "type": "opencollective", ··· 2865 3167 } 2866 3168 }, 2867 3169 "node_modules/chart.js": { 2868 - "version": "4.5.0", 2869 - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.0.tgz", 2870 - "integrity": "sha512-aYeC/jDgSEx8SHWZvANYMioYMZ2KX02W6f6uVfyteuCGcadDLcYVHdfdygsTQkQ4TKn5lghoojAsPj5pu0SnvQ==", 3170 + "version": "4.5.1", 3171 + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.1.tgz", 3172 + "integrity": "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==", 2871 3173 "license": "MIT", 2872 3174 "dependencies": { 2873 3175 "@kurkle/color": "^0.3.0" ··· 2889 3191 "chart.js": ">=3.2.0" 2890 3192 } 2891 3193 }, 2892 - "node_modules/chownr": { 2893 - "version": "3.0.0", 2894 - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", 2895 - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", 2896 - "dev": true, 2897 - "license": "BlueOak-1.0.0", 2898 - "engines": { 2899 - "node": ">=18" 2900 - } 2901 - }, 2902 3194 "node_modules/client-only": { 2903 3195 "version": "0.0.1", 2904 3196 "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", 2905 3197 "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", 2906 3198 "license": "MIT" 2907 3199 }, 2908 - "node_modules/color": { 2909 - "version": "4.2.3", 2910 - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", 2911 - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", 2912 - "license": "MIT", 2913 - "optional": true, 2914 - "dependencies": { 2915 - "color-convert": "^2.0.1", 2916 - "color-string": "^1.9.0" 2917 - }, 2918 - "engines": { 2919 - "node": ">=12.5.0" 2920 - } 2921 - }, 2922 3200 "node_modules/color-convert": { 2923 3201 "version": "2.0.1", 2924 3202 "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 2925 3203 "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 2926 - "devOptional": true, 3204 + "dev": true, 2927 3205 "license": "MIT", 2928 3206 "dependencies": { 2929 3207 "color-name": "~1.1.4" ··· 2936 3214 "version": "1.1.4", 2937 3215 "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 2938 3216 "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 2939 - "devOptional": true, 3217 + "dev": true, 2940 3218 "license": "MIT" 2941 3219 }, 2942 - "node_modules/color-string": { 2943 - "version": "1.9.1", 2944 - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", 2945 - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", 2946 - "license": "MIT", 2947 - "optional": true, 2948 - "dependencies": { 2949 - "color-name": "^1.0.0", 2950 - "simple-swizzle": "^0.2.2" 2951 - } 2952 - }, 2953 3220 "node_modules/concat-map": { 2954 3221 "version": "0.0.1", 2955 3222 "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 2956 3223 "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 3224 + "dev": true, 3225 + "license": "MIT" 3226 + }, 3227 + "node_modules/convert-source-map": { 3228 + "version": "2.0.0", 3229 + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", 3230 + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", 2957 3231 "dev": true, 2958 3232 "license": "MIT" 2959 3233 }, ··· 3102 3376 } 3103 3377 }, 3104 3378 "node_modules/detect-libc": { 3105 - "version": "2.0.4", 3106 - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", 3107 - "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", 3379 + "version": "2.1.2", 3380 + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", 3381 + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", 3108 3382 "devOptional": true, 3109 3383 "license": "Apache-2.0", 3110 3384 "engines": { ··· 3138 3412 "engines": { 3139 3413 "node": ">= 0.4" 3140 3414 } 3415 + }, 3416 + "node_modules/electron-to-chromium": { 3417 + "version": "1.5.244", 3418 + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.244.tgz", 3419 + "integrity": "sha512-OszpBN7xZX4vWMPJwB9illkN/znA8M36GQqQxi6MNy9axWxhOfJyZZJtSLQCpEFLHP2xK33BiWx9aIuIEXVCcw==", 3420 + "dev": true, 3421 + "license": "ISC" 3141 3422 }, 3142 3423 "node_modules/emoji-regex": { 3143 3424 "version": "9.2.2", ··· 3379 3660 "@esbuild/win32-x64": "0.25.9" 3380 3661 } 3381 3662 }, 3663 + "node_modules/escalade": { 3664 + "version": "3.2.0", 3665 + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", 3666 + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", 3667 + "dev": true, 3668 + "license": "MIT", 3669 + "engines": { 3670 + "node": ">=6" 3671 + } 3672 + }, 3382 3673 "node_modules/escape-string-regexp": { 3383 3674 "version": "4.0.0", 3384 3675 "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", ··· 3393 3684 } 3394 3685 }, 3395 3686 "node_modules/eslint": { 3396 - "version": "9.33.0", 3397 - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.33.0.tgz", 3398 - "integrity": "sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA==", 3687 + "version": "9.39.0", 3688 + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.0.tgz", 3689 + "integrity": "sha512-iy2GE3MHrYTL5lrCtMZ0X1KLEKKUjmK0kzwcnefhR66txcEmXZD2YWgR5GNdcEwkNx3a0siYkSvl0vIC+Svjmg==", 3399 3690 "dev": true, 3400 3691 "license": "MIT", 3401 3692 "dependencies": { 3402 - "@eslint-community/eslint-utils": "^4.2.0", 3693 + "@eslint-community/eslint-utils": "^4.8.0", 3403 3694 "@eslint-community/regexpp": "^4.12.1", 3404 - "@eslint/config-array": "^0.21.0", 3405 - "@eslint/config-helpers": "^0.3.1", 3406 - "@eslint/core": "^0.15.2", 3695 + "@eslint/config-array": "^0.21.1", 3696 + "@eslint/config-helpers": "^0.4.2", 3697 + "@eslint/core": "^0.17.0", 3407 3698 "@eslint/eslintrc": "^3.3.1", 3408 - "@eslint/js": "9.33.0", 3409 - "@eslint/plugin-kit": "^0.3.5", 3699 + "@eslint/js": "9.39.0", 3700 + "@eslint/plugin-kit": "^0.4.1", 3410 3701 "@humanfs/node": "^0.16.6", 3411 3702 "@humanwhocodes/module-importer": "^1.0.1", 3412 3703 "@humanwhocodes/retry": "^0.4.2", 3413 3704 "@types/estree": "^1.0.6", 3414 - "@types/json-schema": "^7.0.15", 3415 3705 "ajv": "^6.12.4", 3416 3706 "chalk": "^4.0.0", 3417 3707 "cross-spawn": "^7.0.6", ··· 3454 3744 } 3455 3745 }, 3456 3746 "node_modules/eslint-config-next": { 3457 - "version": "15.4.6", 3458 - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.4.6.tgz", 3459 - "integrity": "sha512-4uznvw5DlTTjrZgYZjMciSdDDMO2SWIuQgUNaFyC2O3Zw3Z91XeIejeVa439yRq2CnJb/KEvE4U2AeN/66FpUA==", 3747 + "version": "16.0.1", 3748 + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.0.1.tgz", 3749 + "integrity": "sha512-wNuHw5gNOxwLUvpg0cu6IL0crrVC9hAwdS/7UwleNkwyaMiWIOAwf8yzXVqBBzL3c9A7jVRngJxjoSpPP1aEhg==", 3460 3750 "dev": true, 3461 3751 "license": "MIT", 3462 3752 "dependencies": { 3463 - "@next/eslint-plugin-next": "15.4.6", 3464 - "@rushstack/eslint-patch": "^1.10.3", 3465 - "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", 3466 - "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", 3753 + "@next/eslint-plugin-next": "16.0.1", 3467 3754 "eslint-import-resolver-node": "^0.3.6", 3468 3755 "eslint-import-resolver-typescript": "^3.5.2", 3469 - "eslint-plugin-import": "^2.31.0", 3756 + "eslint-plugin-import": "^2.32.0", 3470 3757 "eslint-plugin-jsx-a11y": "^6.10.0", 3471 3758 "eslint-plugin-react": "^7.37.0", 3472 - "eslint-plugin-react-hooks": "^5.0.0" 3759 + "eslint-plugin-react-hooks": "^7.0.0", 3760 + "globals": "16.4.0", 3761 + "typescript-eslint": "^8.46.0" 3473 3762 }, 3474 3763 "peerDependencies": { 3475 - "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0", 3764 + "eslint": ">=9.0.0", 3476 3765 "typescript": ">=3.3.1" 3477 3766 }, 3478 3767 "peerDependenciesMeta": { 3479 3768 "typescript": { 3480 3769 "optional": true 3481 3770 } 3771 + } 3772 + }, 3773 + "node_modules/eslint-config-next/node_modules/globals": { 3774 + "version": "16.4.0", 3775 + "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", 3776 + "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", 3777 + "dev": true, 3778 + "license": "MIT", 3779 + "engines": { 3780 + "node": ">=18" 3781 + }, 3782 + "funding": { 3783 + "url": "https://github.com/sponsors/sindresorhus" 3482 3784 } 3483 3785 }, 3484 3786 "node_modules/eslint-import-resolver-node": { ··· 3684 3986 } 3685 3987 }, 3686 3988 "node_modules/eslint-plugin-react-hooks": { 3687 - "version": "5.2.0", 3688 - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", 3689 - "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", 3989 + "version": "7.0.1", 3990 + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz", 3991 + "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==", 3690 3992 "dev": true, 3691 3993 "license": "MIT", 3994 + "dependencies": { 3995 + "@babel/core": "^7.24.4", 3996 + "@babel/parser": "^7.24.4", 3997 + "hermes-parser": "^0.25.1", 3998 + "zod": "^3.25.0 || ^4.0.0", 3999 + "zod-validation-error": "^3.5.0 || ^4.0.0" 4000 + }, 3692 4001 "engines": { 3693 - "node": ">=10" 4002 + "node": ">=18" 3694 4003 }, 3695 4004 "peerDependencies": { 3696 4005 "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" ··· 4015 4324 "url": "https://github.com/sponsors/ljharb" 4016 4325 } 4017 4326 }, 4327 + "node_modules/gensync": { 4328 + "version": "1.0.0-beta.2", 4329 + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", 4330 + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", 4331 + "dev": true, 4332 + "license": "MIT", 4333 + "engines": { 4334 + "node": ">=6.9.0" 4335 + } 4336 + }, 4018 4337 "node_modules/get-intrinsic": { 4019 4338 "version": "1.3.0", 4020 4339 "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", ··· 4258 4577 "node": ">= 0.4" 4259 4578 } 4260 4579 }, 4580 + "node_modules/hermes-estree": { 4581 + "version": "0.25.1", 4582 + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", 4583 + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", 4584 + "dev": true, 4585 + "license": "MIT" 4586 + }, 4587 + "node_modules/hermes-parser": { 4588 + "version": "0.25.1", 4589 + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", 4590 + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", 4591 + "dev": true, 4592 + "license": "MIT", 4593 + "dependencies": { 4594 + "hermes-estree": "0.25.1" 4595 + } 4596 + }, 4261 4597 "node_modules/html-parse-stringify": { 4262 4598 "version": "3.0.1", 4263 4599 "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", ··· 4268 4604 } 4269 4605 }, 4270 4606 "node_modules/i18next": { 4271 - "version": "25.3.6", 4272 - "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.3.6.tgz", 4273 - "integrity": "sha512-dThZ0CTCM3sUG/qS0ZtQYZQcUI6DtBN8yBHK+SKEqihPcEYmjVWh/YJ4luic73Iq6Uxhp6q7LJJntRK5+1t7jQ==", 4607 + "version": "25.6.0", 4608 + "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.6.0.tgz", 4609 + "integrity": "sha512-tTn8fLrwBYtnclpL5aPXK/tAYBLWVvoHM1zdfXoRNLcI+RvtMsoZRV98ePlaW3khHYKuNh/Q65W/+NVFUeIwVw==", 4274 4610 "funding": [ 4275 4611 { 4276 4612 "type": "individual", ··· 4367 4703 "funding": { 4368 4704 "url": "https://github.com/sponsors/ljharb" 4369 4705 } 4370 - }, 4371 - "node_modules/is-arrayish": { 4372 - "version": "0.3.2", 4373 - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", 4374 - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", 4375 - "license": "MIT", 4376 - "optional": true 4377 4706 }, 4378 4707 "node_modules/is-async-function": { 4379 4708 "version": "2.1.1", ··· 4791 5120 } 4792 5121 }, 4793 5122 "node_modules/jiti": { 4794 - "version": "2.5.1", 4795 - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", 4796 - "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", 5123 + "version": "2.6.1", 5124 + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", 5125 + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", 4797 5126 "dev": true, 4798 5127 "license": "MIT", 4799 5128 "bin": { ··· 4820 5149 "js-yaml": "bin/js-yaml.js" 4821 5150 } 4822 5151 }, 5152 + "node_modules/jsesc": { 5153 + "version": "3.1.0", 5154 + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", 5155 + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", 5156 + "dev": true, 5157 + "license": "MIT", 5158 + "bin": { 5159 + "jsesc": "bin/jsesc" 5160 + }, 5161 + "engines": { 5162 + "node": ">=6" 5163 + } 5164 + }, 4823 5165 "node_modules/json-buffer": { 4824 5166 "version": "3.0.1", 4825 5167 "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", ··· 4915 5257 } 4916 5258 }, 4917 5259 "node_modules/lightningcss": { 4918 - "version": "1.30.1", 4919 - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", 4920 - "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", 5260 + "version": "1.30.2", 5261 + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", 5262 + "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==", 4921 5263 "dev": true, 4922 5264 "license": "MPL-2.0", 4923 5265 "dependencies": { ··· 4931 5273 "url": "https://opencollective.com/parcel" 4932 5274 }, 4933 5275 "optionalDependencies": { 4934 - "lightningcss-darwin-arm64": "1.30.1", 4935 - "lightningcss-darwin-x64": "1.30.1", 4936 - "lightningcss-freebsd-x64": "1.30.1", 4937 - "lightningcss-linux-arm-gnueabihf": "1.30.1", 4938 - "lightningcss-linux-arm64-gnu": "1.30.1", 4939 - "lightningcss-linux-arm64-musl": "1.30.1", 4940 - "lightningcss-linux-x64-gnu": "1.30.1", 4941 - "lightningcss-linux-x64-musl": "1.30.1", 4942 - "lightningcss-win32-arm64-msvc": "1.30.1", 4943 - "lightningcss-win32-x64-msvc": "1.30.1" 5276 + "lightningcss-android-arm64": "1.30.2", 5277 + "lightningcss-darwin-arm64": "1.30.2", 5278 + "lightningcss-darwin-x64": "1.30.2", 5279 + "lightningcss-freebsd-x64": "1.30.2", 5280 + "lightningcss-linux-arm-gnueabihf": "1.30.2", 5281 + "lightningcss-linux-arm64-gnu": "1.30.2", 5282 + "lightningcss-linux-arm64-musl": "1.30.2", 5283 + "lightningcss-linux-x64-gnu": "1.30.2", 5284 + "lightningcss-linux-x64-musl": "1.30.2", 5285 + "lightningcss-win32-arm64-msvc": "1.30.2", 5286 + "lightningcss-win32-x64-msvc": "1.30.2" 5287 + } 5288 + }, 5289 + "node_modules/lightningcss-android-arm64": { 5290 + "version": "1.30.2", 5291 + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz", 5292 + "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==", 5293 + "cpu": [ 5294 + "arm64" 5295 + ], 5296 + "dev": true, 5297 + "license": "MPL-2.0", 5298 + "optional": true, 5299 + "os": [ 5300 + "android" 5301 + ], 5302 + "engines": { 5303 + "node": ">= 12.0.0" 5304 + }, 5305 + "funding": { 5306 + "type": "opencollective", 5307 + "url": "https://opencollective.com/parcel" 4944 5308 } 4945 5309 }, 4946 5310 "node_modules/lightningcss-darwin-arm64": { 4947 - "version": "1.30.1", 4948 - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", 4949 - "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", 5311 + "version": "1.30.2", 5312 + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz", 5313 + "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==", 4950 5314 "cpu": [ 4951 5315 "arm64" 4952 5316 ], ··· 4965 5329 } 4966 5330 }, 4967 5331 "node_modules/lightningcss-darwin-x64": { 4968 - "version": "1.30.1", 4969 - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", 4970 - "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", 5332 + "version": "1.30.2", 5333 + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz", 5334 + "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==", 4971 5335 "cpu": [ 4972 5336 "x64" 4973 5337 ], ··· 4986 5350 } 4987 5351 }, 4988 5352 "node_modules/lightningcss-freebsd-x64": { 4989 - "version": "1.30.1", 4990 - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", 4991 - "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", 5353 + "version": "1.30.2", 5354 + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz", 5355 + "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==", 4992 5356 "cpu": [ 4993 5357 "x64" 4994 5358 ], ··· 5007 5371 } 5008 5372 }, 5009 5373 "node_modules/lightningcss-linux-arm-gnueabihf": { 5010 - "version": "1.30.1", 5011 - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", 5012 - "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", 5374 + "version": "1.30.2", 5375 + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz", 5376 + "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==", 5013 5377 "cpu": [ 5014 5378 "arm" 5015 5379 ], ··· 5028 5392 } 5029 5393 }, 5030 5394 "node_modules/lightningcss-linux-arm64-gnu": { 5031 - "version": "1.30.1", 5032 - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", 5033 - "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", 5395 + "version": "1.30.2", 5396 + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz", 5397 + "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==", 5034 5398 "cpu": [ 5035 5399 "arm64" 5036 5400 ], ··· 5049 5413 } 5050 5414 }, 5051 5415 "node_modules/lightningcss-linux-arm64-musl": { 5052 - "version": "1.30.1", 5053 - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", 5054 - "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", 5416 + "version": "1.30.2", 5417 + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz", 5418 + "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==", 5055 5419 "cpu": [ 5056 5420 "arm64" 5057 5421 ], ··· 5070 5434 } 5071 5435 }, 5072 5436 "node_modules/lightningcss-linux-x64-gnu": { 5073 - "version": "1.30.1", 5074 - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", 5075 - "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", 5437 + "version": "1.30.2", 5438 + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz", 5439 + "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==", 5076 5440 "cpu": [ 5077 5441 "x64" 5078 5442 ], ··· 5091 5455 } 5092 5456 }, 5093 5457 "node_modules/lightningcss-linux-x64-musl": { 5094 - "version": "1.30.1", 5095 - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", 5096 - "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", 5458 + "version": "1.30.2", 5459 + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz", 5460 + "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==", 5097 5461 "cpu": [ 5098 5462 "x64" 5099 5463 ], ··· 5112 5476 } 5113 5477 }, 5114 5478 "node_modules/lightningcss-win32-arm64-msvc": { 5115 - "version": "1.30.1", 5116 - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", 5117 - "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", 5479 + "version": "1.30.2", 5480 + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz", 5481 + "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==", 5118 5482 "cpu": [ 5119 5483 "arm64" 5120 5484 ], ··· 5133 5497 } 5134 5498 }, 5135 5499 "node_modules/lightningcss-win32-x64-msvc": { 5136 - "version": "1.30.1", 5137 - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", 5138 - "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", 5500 + "version": "1.30.2", 5501 + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz", 5502 + "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==", 5139 5503 "cpu": [ 5140 5504 "x64" 5141 5505 ], ··· 5189 5553 "loose-envify": "cli.js" 5190 5554 } 5191 5555 }, 5556 + "node_modules/lru-cache": { 5557 + "version": "5.1.1", 5558 + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", 5559 + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", 5560 + "dev": true, 5561 + "license": "ISC", 5562 + "dependencies": { 5563 + "yallist": "^3.0.2" 5564 + } 5565 + }, 5566 + "node_modules/lru-cache/node_modules/yallist": { 5567 + "version": "3.1.1", 5568 + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", 5569 + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", 5570 + "dev": true, 5571 + "license": "ISC" 5572 + }, 5192 5573 "node_modules/magic-string": { 5193 - "version": "0.30.17", 5194 - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", 5195 - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", 5574 + "version": "0.30.21", 5575 + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", 5576 + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", 5196 5577 "dev": true, 5197 5578 "license": "MIT", 5198 5579 "dependencies": { 5199 - "@jridgewell/sourcemap-codec": "^1.5.0" 5580 + "@jridgewell/sourcemap-codec": "^1.5.5" 5200 5581 } 5201 5582 }, 5202 5583 "node_modules/math-intrinsics": { ··· 5256 5637 "url": "https://github.com/sponsors/ljharb" 5257 5638 } 5258 5639 }, 5259 - "node_modules/minipass": { 5260 - "version": "7.1.2", 5261 - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", 5262 - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", 5263 - "dev": true, 5264 - "license": "ISC", 5265 - "engines": { 5266 - "node": ">=16 || 14 >=14.17" 5267 - } 5268 - }, 5269 - "node_modules/minizlib": { 5270 - "version": "3.0.2", 5271 - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", 5272 - "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", 5273 - "dev": true, 5274 - "license": "MIT", 5275 - "dependencies": { 5276 - "minipass": "^7.1.2" 5277 - }, 5278 - "engines": { 5279 - "node": ">= 18" 5280 - } 5281 - }, 5282 - "node_modules/mkdirp": { 5283 - "version": "3.0.1", 5284 - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", 5285 - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", 5286 - "dev": true, 5287 - "license": "MIT", 5288 - "bin": { 5289 - "mkdirp": "dist/cjs/src/bin.js" 5290 - }, 5291 - "engines": { 5292 - "node": ">=10" 5293 - }, 5294 - "funding": { 5295 - "url": "https://github.com/sponsors/isaacs" 5296 - } 5297 - }, 5298 5640 "node_modules/ms": { 5299 5641 "version": "2.1.3", 5300 5642 "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", ··· 5344 5686 "license": "MIT" 5345 5687 }, 5346 5688 "node_modules/next": { 5347 - "version": "15.4.6", 5348 - "resolved": "https://registry.npmjs.org/next/-/next-15.4.6.tgz", 5349 - "integrity": "sha512-us++E/Q80/8+UekzB3SAGs71AlLDsadpFMXVNM/uQ0BMwsh9m3mr0UNQIfjKed8vpWXsASe+Qifrnu1oLIcKEQ==", 5689 + "version": "16.0.1", 5690 + "resolved": "https://registry.npmjs.org/next/-/next-16.0.1.tgz", 5691 + "integrity": "sha512-e9RLSssZwd35p7/vOa+hoDFggUZIUbZhIUSLZuETCwrCVvxOs87NamoUzT+vbcNAL8Ld9GobBnWOA6SbV/arOw==", 5350 5692 "license": "MIT", 5351 5693 "dependencies": { 5352 - "@next/env": "15.4.6", 5694 + "@next/env": "16.0.1", 5353 5695 "@swc/helpers": "0.5.15", 5354 5696 "caniuse-lite": "^1.0.30001579", 5355 5697 "postcss": "8.4.31", ··· 5359 5701 "next": "dist/bin/next" 5360 5702 }, 5361 5703 "engines": { 5362 - "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" 5704 + "node": ">=20.9.0" 5363 5705 }, 5364 5706 "optionalDependencies": { 5365 - "@next/swc-darwin-arm64": "15.4.6", 5366 - "@next/swc-darwin-x64": "15.4.6", 5367 - "@next/swc-linux-arm64-gnu": "15.4.6", 5368 - "@next/swc-linux-arm64-musl": "15.4.6", 5369 - "@next/swc-linux-x64-gnu": "15.4.6", 5370 - "@next/swc-linux-x64-musl": "15.4.6", 5371 - "@next/swc-win32-arm64-msvc": "15.4.6", 5372 - "@next/swc-win32-x64-msvc": "15.4.6", 5373 - "sharp": "^0.34.3" 5707 + "@next/swc-darwin-arm64": "16.0.1", 5708 + "@next/swc-darwin-x64": "16.0.1", 5709 + "@next/swc-linux-arm64-gnu": "16.0.1", 5710 + "@next/swc-linux-arm64-musl": "16.0.1", 5711 + "@next/swc-linux-x64-gnu": "16.0.1", 5712 + "@next/swc-linux-x64-musl": "16.0.1", 5713 + "@next/swc-win32-arm64-msvc": "16.0.1", 5714 + "@next/swc-win32-x64-msvc": "16.0.1", 5715 + "sharp": "^0.34.4" 5374 5716 }, 5375 5717 "peerDependencies": { 5376 5718 "@opentelemetry/api": "^1.1.0", ··· 5422 5764 "engines": { 5423 5765 "node": "^10 || ^12 || >=14" 5424 5766 } 5767 + }, 5768 + "node_modules/node-releases": { 5769 + "version": "2.0.27", 5770 + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", 5771 + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", 5772 + "dev": true, 5773 + "license": "MIT" 5425 5774 }, 5426 5775 "node_modules/object-assign": { 5427 5776 "version": "4.1.1", ··· 5766 6115 "license": "MIT" 5767 6116 }, 5768 6117 "node_modules/react": { 5769 - "version": "19.1.1", 5770 - "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", 5771 - "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==", 6118 + "version": "19.2.0", 6119 + "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", 6120 + "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", 5772 6121 "license": "MIT", 5773 6122 "engines": { 5774 6123 "node": ">=0.10.0" 5775 6124 } 5776 6125 }, 5777 6126 "node_modules/react-dom": { 5778 - "version": "19.1.1", 5779 - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz", 5780 - "integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==", 6127 + "version": "19.2.0", 6128 + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", 6129 + "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", 5781 6130 "license": "MIT", 5782 6131 "dependencies": { 5783 - "scheduler": "^0.26.0" 6132 + "scheduler": "^0.27.0" 5784 6133 }, 5785 6134 "peerDependencies": { 5786 - "react": "^19.1.1" 6135 + "react": "^19.2.0" 5787 6136 } 5788 6137 }, 5789 6138 "node_modules/react-i18next": { 5790 - "version": "15.6.1", 5791 - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.6.1.tgz", 5792 - "integrity": "sha512-uGrzSsOUUe2sDBG/+FJq2J1MM+Y4368/QW8OLEKSFvnDflHBbZhSd1u3UkW0Z06rMhZmnB/AQrhCpYfE5/5XNg==", 6139 + "version": "16.2.3", 6140 + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-16.2.3.tgz", 6141 + "integrity": "sha512-O0t2zvmIz7nHWKNfIL+O/NTIbpTaOPY0vZov779hegbep3IZ+xcqkeVPKWBSXwzdkiv77q8zmq9toKIUys1x3A==", 5793 6142 "license": "MIT", 5794 6143 "dependencies": { 5795 6144 "@babel/runtime": "^7.27.6", 5796 - "html-parse-stringify": "^3.0.1" 6145 + "html-parse-stringify": "^3.0.1", 6146 + "use-sync-external-store": "^1.6.0" 5797 6147 }, 5798 6148 "peerDependencies": { 5799 - "i18next": ">= 23.2.3", 6149 + "i18next": ">= 25.5.2", 5800 6150 "react": ">= 16.8.0", 5801 6151 "typescript": "^5" 5802 6152 }, ··· 5995 6345 } 5996 6346 }, 5997 6347 "node_modules/scheduler": { 5998 - "version": "0.26.0", 5999 - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", 6000 - "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", 6348 + "version": "0.27.0", 6349 + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", 6350 + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", 6001 6351 "license": "MIT" 6002 6352 }, 6003 6353 "node_modules/semver": { ··· 6063 6413 } 6064 6414 }, 6065 6415 "node_modules/sharp": { 6066 - "version": "0.34.3", 6067 - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.3.tgz", 6068 - "integrity": "sha512-eX2IQ6nFohW4DbvHIOLRB3MHFpYqaqvXd3Tp5e/T/dSH83fxaNJQRvDMhASmkNTsNTVF2/OOopzRCt7xokgPfg==", 6416 + "version": "0.34.4", 6417 + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.4.tgz", 6418 + "integrity": "sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA==", 6069 6419 "hasInstallScript": true, 6070 6420 "license": "Apache-2.0", 6071 6421 "optional": true, 6072 6422 "dependencies": { 6073 - "color": "^4.2.3", 6074 - "detect-libc": "^2.0.4", 6423 + "@img/colour": "^1.0.0", 6424 + "detect-libc": "^2.1.0", 6075 6425 "semver": "^7.7.2" 6076 6426 }, 6077 6427 "engines": { ··· 6081 6431 "url": "https://opencollective.com/libvips" 6082 6432 }, 6083 6433 "optionalDependencies": { 6084 - "@img/sharp-darwin-arm64": "0.34.3", 6085 - "@img/sharp-darwin-x64": "0.34.3", 6086 - "@img/sharp-libvips-darwin-arm64": "1.2.0", 6087 - "@img/sharp-libvips-darwin-x64": "1.2.0", 6088 - "@img/sharp-libvips-linux-arm": "1.2.0", 6089 - "@img/sharp-libvips-linux-arm64": "1.2.0", 6090 - "@img/sharp-libvips-linux-ppc64": "1.2.0", 6091 - "@img/sharp-libvips-linux-s390x": "1.2.0", 6092 - "@img/sharp-libvips-linux-x64": "1.2.0", 6093 - "@img/sharp-libvips-linuxmusl-arm64": "1.2.0", 6094 - "@img/sharp-libvips-linuxmusl-x64": "1.2.0", 6095 - "@img/sharp-linux-arm": "0.34.3", 6096 - "@img/sharp-linux-arm64": "0.34.3", 6097 - "@img/sharp-linux-ppc64": "0.34.3", 6098 - "@img/sharp-linux-s390x": "0.34.3", 6099 - "@img/sharp-linux-x64": "0.34.3", 6100 - "@img/sharp-linuxmusl-arm64": "0.34.3", 6101 - "@img/sharp-linuxmusl-x64": "0.34.3", 6102 - "@img/sharp-wasm32": "0.34.3", 6103 - "@img/sharp-win32-arm64": "0.34.3", 6104 - "@img/sharp-win32-ia32": "0.34.3", 6105 - "@img/sharp-win32-x64": "0.34.3" 6434 + "@img/sharp-darwin-arm64": "0.34.4", 6435 + "@img/sharp-darwin-x64": "0.34.4", 6436 + "@img/sharp-libvips-darwin-arm64": "1.2.3", 6437 + "@img/sharp-libvips-darwin-x64": "1.2.3", 6438 + "@img/sharp-libvips-linux-arm": "1.2.3", 6439 + "@img/sharp-libvips-linux-arm64": "1.2.3", 6440 + "@img/sharp-libvips-linux-ppc64": "1.2.3", 6441 + "@img/sharp-libvips-linux-s390x": "1.2.3", 6442 + "@img/sharp-libvips-linux-x64": "1.2.3", 6443 + "@img/sharp-libvips-linuxmusl-arm64": "1.2.3", 6444 + "@img/sharp-libvips-linuxmusl-x64": "1.2.3", 6445 + "@img/sharp-linux-arm": "0.34.4", 6446 + "@img/sharp-linux-arm64": "0.34.4", 6447 + "@img/sharp-linux-ppc64": "0.34.4", 6448 + "@img/sharp-linux-s390x": "0.34.4", 6449 + "@img/sharp-linux-x64": "0.34.4", 6450 + "@img/sharp-linuxmusl-arm64": "0.34.4", 6451 + "@img/sharp-linuxmusl-x64": "0.34.4", 6452 + "@img/sharp-wasm32": "0.34.4", 6453 + "@img/sharp-win32-arm64": "0.34.4", 6454 + "@img/sharp-win32-ia32": "0.34.4", 6455 + "@img/sharp-win32-x64": "0.34.4" 6106 6456 } 6107 6457 }, 6108 6458 "node_modules/shebang-command": { ··· 6204 6554 "url": "https://github.com/sponsors/ljharb" 6205 6555 } 6206 6556 }, 6207 - "node_modules/simple-swizzle": { 6208 - "version": "0.2.2", 6209 - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", 6210 - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", 6211 - "license": "MIT", 6212 - "optional": true, 6213 - "dependencies": { 6214 - "is-arrayish": "^0.3.1" 6215 - } 6216 - }, 6217 6557 "node_modules/source-map-js": { 6218 6558 "version": "1.2.1", 6219 6559 "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", ··· 6435 6775 } 6436 6776 }, 6437 6777 "node_modules/tailwindcss": { 6438 - "version": "4.1.11", 6439 - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz", 6440 - "integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==", 6778 + "version": "4.1.16", 6779 + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.16.tgz", 6780 + "integrity": "sha512-pONL5awpaQX4LN5eiv7moSiSPd/DLDzKVRJz8Q9PgzmAdd1R4307GQS2ZpfiN7ZmekdQrfhZZiSE5jkLR4WNaA==", 6441 6781 "dev": true, 6442 6782 "license": "MIT" 6443 6783 }, 6444 6784 "node_modules/tapable": { 6445 - "version": "2.2.2", 6446 - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", 6447 - "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", 6785 + "version": "2.3.0", 6786 + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", 6787 + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", 6448 6788 "dev": true, 6449 6789 "license": "MIT", 6450 6790 "engines": { 6451 6791 "node": ">=6" 6452 - } 6453 - }, 6454 - "node_modules/tar": { 6455 - "version": "7.4.3", 6456 - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", 6457 - "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", 6458 - "dev": true, 6459 - "license": "ISC", 6460 - "dependencies": { 6461 - "@isaacs/fs-minipass": "^4.0.0", 6462 - "chownr": "^3.0.0", 6463 - "minipass": "^7.1.2", 6464 - "minizlib": "^3.0.1", 6465 - "mkdirp": "^3.0.1", 6466 - "yallist": "^5.0.0" 6467 6792 }, 6468 - "engines": { 6469 - "node": ">=18" 6793 + "funding": { 6794 + "type": "opencollective", 6795 + "url": "https://opencollective.com/webpack" 6470 6796 } 6471 6797 }, 6472 6798 "node_modules/tinyglobby": { ··· 6563 6889 "license": "0BSD" 6564 6890 }, 6565 6891 "node_modules/tsx": { 6566 - "version": "4.20.4", 6567 - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.4.tgz", 6568 - "integrity": "sha512-yyxBKfORQ7LuRt/BQKBXrpcq59ZvSW0XxwfjAt3w2/8PmdxaFzijtMhTawprSHhpzeM5BgU2hXHG3lklIERZXg==", 6892 + "version": "4.20.6", 6893 + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.6.tgz", 6894 + "integrity": "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==", 6569 6895 "dev": true, 6570 6896 "license": "MIT", 6571 6897 "dependencies": { ··· 6674 7000 } 6675 7001 }, 6676 7002 "node_modules/typescript": { 6677 - "version": "5.9.2", 6678 - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", 6679 - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", 7003 + "version": "5.9.3", 7004 + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", 7005 + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", 6680 7006 "devOptional": true, 6681 7007 "license": "Apache-2.0", 6682 7008 "bin": { ··· 6687 7013 "node": ">=14.17" 6688 7014 } 6689 7015 }, 7016 + "node_modules/typescript-eslint": { 7017 + "version": "8.46.2", 7018 + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.46.2.tgz", 7019 + "integrity": "sha512-vbw8bOmiuYNdzzV3lsiWv6sRwjyuKJMQqWulBOU7M0RrxedXledX8G8kBbQeiOYDnTfiXz0Y4081E1QMNB6iQg==", 7020 + "dev": true, 7021 + "license": "MIT", 7022 + "dependencies": { 7023 + "@typescript-eslint/eslint-plugin": "8.46.2", 7024 + "@typescript-eslint/parser": "8.46.2", 7025 + "@typescript-eslint/typescript-estree": "8.46.2", 7026 + "@typescript-eslint/utils": "8.46.2" 7027 + }, 7028 + "engines": { 7029 + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 7030 + }, 7031 + "funding": { 7032 + "type": "opencollective", 7033 + "url": "https://opencollective.com/typescript-eslint" 7034 + }, 7035 + "peerDependencies": { 7036 + "eslint": "^8.57.0 || ^9.0.0", 7037 + "typescript": ">=4.8.4 <6.0.0" 7038 + } 7039 + }, 6690 7040 "node_modules/unbox-primitive": { 6691 7041 "version": "1.1.0", 6692 7042 "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", ··· 6707 7057 } 6708 7058 }, 6709 7059 "node_modules/undici-types": { 6710 - "version": "7.10.0", 6711 - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", 6712 - "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", 7060 + "version": "7.16.0", 7061 + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", 7062 + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", 6713 7063 "dev": true, 6714 7064 "license": "MIT" 6715 7065 }, ··· 6748 7098 "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" 6749 7099 } 6750 7100 }, 7101 + "node_modules/update-browserslist-db": { 7102 + "version": "1.1.4", 7103 + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", 7104 + "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", 7105 + "dev": true, 7106 + "funding": [ 7107 + { 7108 + "type": "opencollective", 7109 + "url": "https://opencollective.com/browserslist" 7110 + }, 7111 + { 7112 + "type": "tidelift", 7113 + "url": "https://tidelift.com/funding/github/npm/browserslist" 7114 + }, 7115 + { 7116 + "type": "github", 7117 + "url": "https://github.com/sponsors/ai" 7118 + } 7119 + ], 7120 + "license": "MIT", 7121 + "dependencies": { 7122 + "escalade": "^3.2.0", 7123 + "picocolors": "^1.1.1" 7124 + }, 7125 + "bin": { 7126 + "update-browserslist-db": "cli.js" 7127 + }, 7128 + "peerDependencies": { 7129 + "browserslist": ">= 4.21.0" 7130 + } 7131 + }, 6751 7132 "node_modules/uri-js": { 6752 7133 "version": "4.4.1", 6753 7134 "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", ··· 6756 7137 "license": "BSD-2-Clause", 6757 7138 "dependencies": { 6758 7139 "punycode": "^2.1.0" 7140 + } 7141 + }, 7142 + "node_modules/use-sync-external-store": { 7143 + "version": "1.6.0", 7144 + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", 7145 + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", 7146 + "license": "MIT", 7147 + "peerDependencies": { 7148 + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 6759 7149 } 6760 7150 }, 6761 7151 "node_modules/void-elements": { ··· 6882 7272 "node": ">=0.10.0" 6883 7273 } 6884 7274 }, 6885 - "node_modules/yallist": { 6886 - "version": "5.0.0", 6887 - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", 6888 - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", 6889 - "dev": true, 6890 - "license": "BlueOak-1.0.0", 6891 - "engines": { 6892 - "node": ">=18" 6893 - } 6894 - }, 6895 7275 "node_modules/yocto-queue": { 6896 7276 "version": "0.1.0", 6897 7277 "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", ··· 6903 7283 }, 6904 7284 "funding": { 6905 7285 "url": "https://github.com/sponsors/sindresorhus" 7286 + } 7287 + }, 7288 + "node_modules/zod": { 7289 + "version": "4.1.12", 7290 + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", 7291 + "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", 7292 + "dev": true, 7293 + "license": "MIT", 7294 + "funding": { 7295 + "url": "https://github.com/sponsors/colinhacks" 7296 + } 7297 + }, 7298 + "node_modules/zod-validation-error": { 7299 + "version": "4.0.2", 7300 + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", 7301 + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", 7302 + "dev": true, 7303 + "license": "MIT", 7304 + "engines": { 7305 + "node": ">=18.0.0" 7306 + }, 7307 + "peerDependencies": { 7308 + "zod": "^3.25.0 || ^4.0.0" 6906 7309 } 6907 7310 } 6908 7311 }
+10 -10
package.json
··· 12 12 "prewarm": "tsx src/scripts/prewarm.ts" 13 13 }, 14 14 "dependencies": { 15 - "@duckdb/node-api": "^1.3.2-alpha.25", 15 + "@duckdb/node-api": "^1.4.1-r.4", 16 16 "@heroicons/react": "^2.2.0", 17 - "chart.js": "^4.5.0", 17 + "chart.js": "^4.5.1", 18 18 "chartjs-plugin-zoom": "^2.2.0", 19 - "i18next": "^25.3.6", 20 - "next": "15.4.6", 21 - "react": "19.1.1", 22 - "react-dom": "19.1.1", 23 - "react-i18next": "^15.6.1", 19 + "i18next": "^25.6.0", 20 + "next": "16.0.1", 21 + "react": "19.2.0", 22 + "react-dom": "19.2.0", 23 + "react-i18next": "^16.2.3", 24 24 "suncalc": "^1.9.0" 25 25 }, 26 26 "devDependencies": { ··· 28 28 "@types/node": "^24", 29 29 "@types/react": "^19", 30 30 "@types/react-dom": "^19", 31 - "eslint": "9.33.0", 32 - "eslint-config-next": "15.4.6", 31 + "eslint": "9.39.0", 32 + "eslint-config-next": "16.0.1", 33 33 "tailwindcss": "^4", 34 - "tsx": "^4.7.0", 34 + "tsx": "^4.20.6", 35 35 "typescript": "^5" 36 36 } 37 37 }
+362
src/app/api/forecast/route.ts
··· 1 + import { NextResponse } from "next/server"; 2 + 3 + // Geosphere API endpoints 4 + const TAWES_STATIONS_ENDPOINT = "https://dataset.api.hub.geosphere.at/v1/station/current/tawes-v1-10min/metadata"; 5 + const FORECAST_ENDPOINT = "https://dataset.api.hub.geosphere.at/v1/timeseries/forecast/ensemble-v1-1h-2500m"; 6 + 7 + // Cache for station data to avoid repeated API calls 8 + let stationsCache: any = null; 9 + let stationsCacheTime: number = 0; 10 + const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes 11 + 12 + export const runtime = "nodejs"; 13 + 14 + /** 15 + * API route to get weather stations list from Geosphere API 16 + * This function handles GET requests to /api/forecast?action=stations or /api/forecast?action=forecast 17 + * 18 + * @returns {Promise<NextResponse>} A JSON response containing the stations data or forecast data, or an error message 19 + */ 20 + export async function GET(req: Request) { 21 + try { 22 + const { searchParams } = new URL(req.url); 23 + const action = searchParams.get("action") || "stations"; 24 + 25 + if (action === "stations") { 26 + // Check cache first 27 + const now = Date.now(); 28 + if (stationsCache && (now - stationsCacheTime) < CACHE_DURATION) { 29 + return NextResponse.json(stationsCache, { status: 200 }); 30 + } 31 + 32 + // Fetch TAWES stations data from Geosphere API 33 + const response = await fetch(TAWES_STATIONS_ENDPOINT); 34 + if (!response.ok) { 35 + throw new Error(`Failed to fetch stations: ${response.status} ${response.statusText}`); 36 + } 37 + 38 + const data = await response.json(); 39 + 40 + // Group stations by state (Bundesland) 41 + const stationsByState: Record<string, any[]> = {}; 42 + 43 + data.stations.forEach((station: any) => { 44 + const state = station.state || "Unknown"; 45 + if (!stationsByState[state]) { 46 + stationsByState[state] = []; 47 + } 48 + stationsByState[state].push({ 49 + id: station.id, 50 + name: station.name, 51 + state: station.state, 52 + lat: station.lat, 53 + lon: station.lon, 54 + altitude: station.altitude 55 + }); 56 + }); 57 + 58 + // Sort states alphabetically and stations within each state by name 59 + const sortedStates = Object.keys(stationsByState).sort(); 60 + const sortedStations: Record<string, any[]> = {}; 61 + 62 + sortedStates.forEach(state => { 63 + sortedStations[state] = stationsByState[state].sort((a, b) => 64 + a.name.localeCompare(b.name) 65 + ); 66 + }); 67 + 68 + // Cache the result 69 + stationsCache = { stations: sortedStations }; 70 + stationsCacheTime = now; 71 + 72 + return NextResponse.json(stationsCache, { status: 200 }); 73 + } else if (action === "forecast") { 74 + const stationId = searchParams.get("stationId"); 75 + if (!stationId) { 76 + return NextResponse.json({ error: "stationId parameter is required" }, { status: 400 }); 77 + } 78 + 79 + // First get station details 80 + const stationsResponse = await fetch(TAWES_STATIONS_ENDPOINT); 81 + if (!stationsResponse.ok) { 82 + throw new Error(`Failed to fetch stations: ${stationsResponse.status} ${stationsResponse.statusText}`); 83 + } 84 + 85 + const stationsData = await stationsResponse.json(); 86 + const station = stationsData.stations.find((s: any) => s.id === stationId); 87 + 88 + if (!station) { 89 + return NextResponse.json({ error: "Station not found" }, { status: 404 }); 90 + } 91 + 92 + // Fetch forecast data for the specified station coordinates 93 + // We'll get temperature (t2m_p50), precipitation (rr_p50), and wind (u10m_p50, v10m_p50) for the next 7 days 94 + const params = "t2m_p50,rr_p50,u10m_p50,v10m_p50"; 95 + const lat = station.lat; 96 + const lon = station.lon; 97 + 98 + // For timeseries forecast, we need to use lat/lon coordinates in the correct format 99 + const response = await fetch(`${FORECAST_ENDPOINT}?parameters=${params}&lat_lon=${lat},${lon}`); 100 + 101 + if (!response.ok) { 102 + throw new Error(`Failed to fetch forecast: ${response.status} ${response.statusText}`); 103 + } 104 + 105 + const data = await response.json(); 106 + 107 + // Process the forecast data to extract 7-day forecast 108 + const forecastData: any[] = []; 109 + 110 + if (data && data.features && data.features.length > 0 && data.timestamps) { 111 + const feature = data.features[0]; 112 + if (feature.properties && feature.properties.parameters) { 113 + // Extract temperature, precipitation, and wind data 114 + const tempParam = feature.properties.parameters.t2m_p50; 115 + const precipParam = feature.properties.parameters.rr_p50; 116 + const uWindParam = feature.properties.parameters.u10m_p50; 117 + const vWindParam = feature.properties.parameters.v10m_p50; 118 + 119 + const tempData = tempParam?.data || []; 120 + const precipData = precipParam?.data || []; 121 + const uWindData = uWindParam?.data || []; 122 + const vWindData = vWindParam?.data || []; 123 + const timestamps = data.timestamps || []; 124 + 125 + // Combine data for the next 7 days (168 hours) 126 + const now = new Date(); 127 + const sevenDaysLater = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000); 128 + 129 + // Process temperature data 130 + tempData.forEach((tempValue: any, index: number) => { 131 + if (index < timestamps.length) { 132 + const time = timestamps[index]; 133 + const tempDate = new Date(time); 134 + 135 + // Only include data for the next 7 days 136 + if (tempDate >= now && tempDate <= sevenDaysLater) { 137 + const precipValue = index < precipData.length ? precipData[index] : null; 138 + const uWind = index < uWindData.length ? uWindData[index] : null; 139 + const vWind = index < vWindData.length ? vWindData[index] : null; 140 + 141 + // Calculate wind speed from u and v components: speed = sqrt(u² + v²) 142 + let windSpeed = null; 143 + if (uWind !== null && vWind !== null) { 144 + windSpeed = Math.sqrt(uWind * uWind + vWind * vWind) * 3.6; // Convert m/s to km/h 145 + } 146 + 147 + forecastData.push({ 148 + time: time, 149 + temperature: tempValue !== null ? parseFloat(tempValue) : null, 150 + precipitation: precipValue !== null ? parseFloat(precipValue) : null, 151 + windSpeed: windSpeed !== null ? parseFloat(windSpeed.toFixed(1)) : null 152 + }); 153 + } 154 + } 155 + }); 156 + } 157 + } 158 + 159 + return NextResponse.json({ forecast: forecastData }, { status: 200 }); 160 + } else if (action === "openweather") { 161 + const stationId = searchParams.get("stationId"); 162 + if (!stationId) { 163 + return NextResponse.json({ error: "stationId parameter is required" }, { status: 400 }); 164 + } 165 + 166 + // Get OpenWeatherMap API key from environment 167 + const apiKey = process.env.OPENWEATHER_API_KEY; 168 + if (!apiKey) { 169 + return NextResponse.json({ error: "OpenWeatherMap API key not configured" }, { status: 500 }); 170 + } 171 + 172 + // First get station details for coordinates 173 + const stationsResponse = await fetch(TAWES_STATIONS_ENDPOINT); 174 + if (!stationsResponse.ok) { 175 + throw new Error(`Failed to fetch stations: ${stationsResponse.status} ${stationsResponse.statusText}`); 176 + } 177 + 178 + const stationsData = await stationsResponse.json(); 179 + const station = stationsData.stations.find((s: any) => s.id === stationId); 180 + 181 + if (!station) { 182 + return NextResponse.json({ error: "Station not found" }, { status: 404 }); 183 + } 184 + 185 + const lat = station.lat; 186 + const lon = station.lon; 187 + 188 + // Fetch 5-day forecast from OpenWeatherMap (FREE API) 189 + const owmUrl = `https://api.openweathermap.org/data/2.5/forecast?lat=${lat}&lon=${lon}&units=metric&appid=${apiKey}`; 190 + const owmResponse = await fetch(owmUrl); 191 + 192 + if (!owmResponse.ok) { 193 + throw new Error(`Failed to fetch OpenWeatherMap forecast: ${owmResponse.status} ${owmResponse.statusText}`); 194 + } 195 + 196 + const owmData = await owmResponse.json(); 197 + 198 + // Process OpenWeatherMap 3-hour forecast data into daily aggregates 199 + const dailyMap: Record<string, any[]> = {}; 200 + 201 + owmData.list?.forEach((item: any) => { 202 + const date = new Date(item.dt * 1000); 203 + const dateKey = date.toISOString().split('T')[0]; // YYYY-MM-DD 204 + 205 + if (!dailyMap[dateKey]) { 206 + dailyMap[dateKey] = []; 207 + } 208 + dailyMap[dateKey].push(item); 209 + }); 210 + 211 + // Aggregate 3-hour data into daily forecasts 212 + const dailyForecast = Object.entries(dailyMap).map(([dateKey, items]) => { 213 + const temps = items.map(i => i.main.temp); 214 + const tempMins = items.map(i => i.main.temp_min); 215 + const tempMaxs = items.map(i => i.main.temp_max); 216 + const precipitations = items.map(i => (i.rain?.['3h'] ?? 0) + (i.snow?.['3h'] ?? 0)); 217 + const windSpeeds = items.map(i => i.wind.speed); 218 + const windGusts = items.map(i => i.wind.gust ?? 0); 219 + const pops = items.map(i => i.pop ?? 0); 220 + 221 + return { 222 + date: new Date(dateKey + 'T12:00:00').toISOString(), 223 + tempMin: Math.min(...tempMins), 224 + tempMax: Math.max(...tempMaxs), 225 + tempDay: temps.reduce((sum, t) => sum + t, 0) / temps.length, 226 + precipitation: precipitations.reduce((sum, p) => sum + p, 0), 227 + windSpeed: windSpeeds.reduce((sum, w) => sum + w, 0) / windSpeeds.length * 3.6, // Convert m/s to km/h 228 + windGust: Math.max(...windGusts) * 3.6, // Convert m/s to km/h 229 + humidity: items.reduce((sum, i) => sum + i.main.humidity, 0) / items.length, 230 + pressure: items.reduce((sum, i) => sum + i.main.pressure, 0) / items.length, 231 + weather: items[Math.floor(items.length / 2)].weather?.[0] ?? null, // Use midday weather 232 + clouds: items.reduce((sum, i) => sum + i.clouds.all, 0) / items.length, 233 + pop: Math.max(...pops) // Max probability of precipitation 234 + }; 235 + }).sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()); 236 + 237 + return NextResponse.json({ forecast: dailyForecast }, { status: 200 }); 238 + } else if (action === "meteoblue") { 239 + const stationId = searchParams.get("stationId"); 240 + if (!stationId) { 241 + return NextResponse.json({ error: "stationId parameter is required" }, { status: 400 }); 242 + } 243 + 244 + // Get Meteoblue API key from environment 245 + const apiKey = process.env.METEOBLUE_API_KEY; 246 + if (!apiKey) { 247 + return NextResponse.json({ error: "Meteoblue API key not configured" }, { status: 500 }); 248 + } 249 + 250 + // First get station details for coordinates 251 + const stationsResponse = await fetch(TAWES_STATIONS_ENDPOINT); 252 + if (!stationsResponse.ok) { 253 + throw new Error(`Failed to fetch stations: ${stationsResponse.status} ${stationsResponse.statusText}`); 254 + } 255 + 256 + const stationsData = await stationsResponse.json(); 257 + const station = stationsData.stations.find((s: any) => s.id === stationId); 258 + 259 + if (!station) { 260 + return NextResponse.json({ error: "Station not found" }, { status: 404 }); 261 + } 262 + 263 + const lat = station.lat; 264 + const lon = station.lon; 265 + 266 + // Fetch 7-day forecast from Meteoblue (FREE API) 267 + // Using basic package with daily data 268 + const mbUrl = `https://my.meteoblue.com/packages/basic-day?apikey=${apiKey}&lat=${lat}&lon=${lon}&asl=500&format=json&temperature=C&windspeed=kmh&precipitationamount=mm&timeformat=iso8601`; 269 + const mbResponse = await fetch(mbUrl); 270 + 271 + if (!mbResponse.ok) { 272 + throw new Error(`Failed to fetch Meteoblue forecast: ${mbResponse.status} ${mbResponse.statusText}`); 273 + } 274 + 275 + const mbData = await mbResponse.json(); 276 + 277 + // Process Meteoblue daily forecast (7 days) 278 + const dailyForecast: any[] = []; 279 + 280 + if (mbData.data_day) { 281 + const data = mbData.data_day; 282 + const timeArray = data.time || []; 283 + const tempMaxArray = data.temperature_max || []; 284 + const tempMinArray = data.temperature_min || []; 285 + const tempMeanArray = data.temperature_mean || []; 286 + const precipArray = data.precipitation || []; 287 + const windSpeedArray = data.windspeed_mean || []; 288 + const windGustArray = data.windspeed_max || []; 289 + const pictoCodeArray = data.pictocode || []; 290 + 291 + // Take first 7 days 292 + for (let i = 0; i < Math.min(7, timeArray.length); i++) { 293 + dailyForecast.push({ 294 + date: timeArray[i], 295 + tempMin: tempMinArray[i] ?? null, 296 + tempMax: tempMaxArray[i] ?? null, 297 + tempMean: tempMeanArray[i] ?? null, 298 + precipitation: precipArray[i] ?? 0, 299 + windSpeed: windSpeedArray[i] ?? null, 300 + windGust: windGustArray[i] ?? null, 301 + pictocode: pictoCodeArray[i] ?? null 302 + }); 303 + } 304 + } 305 + 306 + return NextResponse.json({ forecast: dailyForecast }, { status: 200 }); 307 + } else if (action === "meteogram") { 308 + const stationId = searchParams.get("stationId"); 309 + if (!stationId) { 310 + return NextResponse.json({ error: "stationId parameter is required" }, { status: 400 }); 311 + } 312 + 313 + // Get Meteoblue API key from environment 314 + const apiKey = process.env.METEOBLUE_API_KEY; 315 + if (!apiKey) { 316 + return NextResponse.json({ error: "Meteoblue API key not configured" }, { status: 500 }); 317 + } 318 + 319 + // First get station details for coordinates 320 + const stationsResponse = await fetch(TAWES_STATIONS_ENDPOINT); 321 + if (!stationsResponse.ok) { 322 + throw new Error(`Failed to fetch stations: ${stationsResponse.status} ${stationsResponse.statusText}`); 323 + } 324 + 325 + const stationsData = await stationsResponse.json(); 326 + const station = stationsData.stations.find((s: any) => s.id === stationId); 327 + 328 + if (!station) { 329 + return NextResponse.json({ error: "Station not found" }, { status: 404 }); 330 + } 331 + 332 + const lat = station.lat; 333 + const lon = station.lon; 334 + const altitude = station.altitude || 500; 335 + const name = encodeURIComponent(station.name); 336 + 337 + // Fetch meteogram image from Meteoblue 338 + const meteogramUrl = `https://my.meteoblue.com/images/meteogram?lat=${lat}&lon=${lon}&asl=${altitude}&tz=Europe%2FVienna&apikey=${apiKey}&format=webp&dpi=72&lang=de&temperature_units=C&precipitation_units=mm&windspeed_units=kmh&location_name=${name}`; 339 + 340 + const imageResponse = await fetch(meteogramUrl); 341 + 342 + if (!imageResponse.ok) { 343 + throw new Error(`Failed to fetch meteogram: ${imageResponse.status} ${imageResponse.statusText}`); 344 + } 345 + 346 + // Return the image directly 347 + const imageBuffer = await imageResponse.arrayBuffer(); 348 + return new NextResponse(imageBuffer, { 349 + status: 200, 350 + headers: { 351 + 'Content-Type': 'image/webp', 352 + 'Cache-Control': 'public, max-age=3600', // Cache for 1 hour 353 + }, 354 + }); 355 + } else { 356 + return NextResponse.json({ error: "Invalid action parameter" }, { status: 400 }); 357 + } 358 + } catch (e: any) { 359 + console.error("Forecast API error:", e); 360 + return NextResponse.json({ error: String(e?.message || e) }, { status: 500 }); 361 + } 362 + }
+11 -1
src/app/page.tsx
··· 5 5 import Realtime from "@/components/Realtime"; 6 6 import Gauges from "@/components/Gauges"; 7 7 import Statistics from "@/components/Statistics"; 8 + import Forecast from "@/components/Forecast"; 8 9 import { useTranslation } from "react-i18next"; 9 10 import LanguageSwitcher from "@/components/LanguageSwitcher"; 10 11 import { RealtimeProvider } from "@/contexts/RealtimeContext"; ··· 15 16 * - Realtime: A list of current sensor readings. 16 17 * - Graphics: A set of gauges and visual displays for current data. 17 18 * - Saved: A dashboard for viewing historical data with charts. 19 + * - Statistics: Statistical analysis of historical data. 20 + * - Forecast: 7-day weather forecast from Geosphere API. 18 21 * 19 22 * @returns The Home page component. 20 23 */ 21 24 export default function Home() { 22 25 const { t } = useTranslation(); 23 - const [tab, setTab] = useState<"rt" | "gfx" | "stored" | "stats">("rt"); 26 + const [tab, setTab] = useState<"rt" | "gfx" | "stored" | "stats" | "forecast">("rt"); 24 27 return ( 25 28 <RealtimeProvider> 26 29 <div className="min-h-screen w-full bg-gray-50 dark:bg-neutral-950 text-gray-900 dark:text-gray-100 p-4 sm:p-6"> ··· 39 42 {t("tabs.graphics")} 40 43 </button> 41 44 <button 45 + className={`px-3 py-2 text-sm font-medium rounded-t ${tab === "forecast" ? "bg-white dark:bg-neutral-900 border border-b-0 border-gray-200 dark:border-neutral-800" : "text-gray-600 hover:text-gray-900"}`} 46 + onClick={() => setTab("forecast")} 47 + > 48 + {t("tabs.forecast", "Forecast")} 49 + </button> 50 + <button 42 51 className={`px-3 py-2 text-sm font-medium rounded-t ${tab === "stored" ? "bg-white dark:bg-neutral-900 border border-b-0 border-gray-200 dark:border-neutral-800" : "text-gray-600 hover:text-gray-900"}`} 43 52 onClick={() => setTab("stored")} 44 53 > ··· 58 67 {tab === "gfx" && <Gauges />} 59 68 {tab === "stored" && <Dashboard />} 60 69 {tab === "stats" && <Statistics />} 70 + {tab === "forecast" && <Forecast />} 61 71 </div> 62 72 </div> 63 73 </div>
+681
src/components/Forecast.tsx
··· 1 + "use client"; 2 + 3 + import React, { useState, useEffect } from "react"; 4 + import { API_ENDPOINTS } from "@/constants"; 5 + import { useTranslation } from "react-i18next"; 6 + 7 + interface Station { 8 + id: string; 9 + name: string; 10 + state: string; 11 + lat: number; 12 + lon: number; 13 + altitude: number; 14 + } 15 + 16 + interface ForecastDataPoint { 17 + time: string; 18 + temperature: number | null; 19 + precipitation: number | null; 20 + windSpeed?: number | null; 21 + } 22 + 23 + interface OpenWeatherDay { 24 + date: string; 25 + tempMin: number | null; 26 + tempMax: number | null; 27 + tempDay: number | null; 28 + precipitation: number; 29 + windSpeed: number | null; 30 + windGust: number | null; 31 + humidity: number | null; 32 + pressure: number | null; 33 + weather: any; 34 + clouds: number | null; 35 + pop: number | null; 36 + } 37 + 38 + interface MeteoblueDay { 39 + date: string; 40 + tempMin: number | null; 41 + tempMax: number | null; 42 + tempMean: number | null; 43 + precipitation: number; 44 + windSpeed: number | null; 45 + windGust: number | null; 46 + pictocode: number | null; 47 + } 48 + 49 + // Map Meteoblue pictocode to weather emoji and description 50 + // Based on: https://content.meteoblue.com/en/help/standards/symbols-and-pictograms 51 + function getWeatherEmoji(pictocode: number): string { 52 + const weatherMap: Record<number, string> = { 53 + 1: "☀️", // Clear, cloudless sky 54 + 2: "🌤️", // Clear, few cirrus 55 + 3: "⛅", // Clear with cirrus 56 + 4: "🌥️", // Clear with few low clouds 57 + 5: "🌥️", // Clear with few low clouds and few cirrus 58 + 6: "🌥️", // Clear with few low clouds and cirrus 59 + 7: "🌤️", // Partly cloudy 60 + 8: "🌤️", // Partly cloudy and few cirrus 61 + 9: "⛅", // Partly cloudy and cirrus 62 + 10: "☁️", // Mixed with some thunderstorm clouds possible 63 + 11: "🌫️", // Fog/low stratus clouds 64 + 12: "🌫️", // Fog/low stratus clouds with cirrus 65 + 13: "🌫️", // Fog/low stratus clouds with few cirrus 66 + 14: "🌫️", // Fog/low stratus clouds with thunderstorm clouds possible 67 + 15: "🌧️", // Precipitation possible 68 + 16: "🌧️", // Precipitation 69 + 17: "⛈️", // Thunderstorms 70 + 18: "❄️", // Precipitation, possible thunderstorms 71 + 19: "🌨️", // Snow 72 + 20: "🌨️", // Precipitation, snow mixed 73 + 21: "🌧️", // Overcast with rain 74 + 22: "🌨️", // Overcast with snow 75 + 23: "🌧️", // Overcast with possible thunderstorms 76 + 24: "⛈️", // Thunderstorms, possible hail 77 + 25: "🌧️", // Light rain 78 + 26: "🌧️", // Rain 79 + 27: "🌧️", // Heavy rain 80 + }; 81 + 82 + return weatherMap[pictocode] || "🌡️"; 83 + } 84 + 85 + 86 + export default function Forecast() { 87 + const { t } = useTranslation(); 88 + const [stations, setStations] = useState<Record<string, Station[]>>({}); 89 + const [selectedStation, setSelectedStation] = useState<string>(""); 90 + const [forecastData, setForecastData] = useState<ForecastDataPoint[]>([]); 91 + const [openWeatherData, setOpenWeatherData] = useState<OpenWeatherDay[]>([]); 92 + const [meteoblueData, setMeteoblueData] = useState<MeteoblueDay[]>([]); 93 + const [loading, setLoading] = useState<boolean>(false); 94 + const [loadingOWM, setLoadingOWM] = useState<boolean>(false); 95 + const [loadingMB, setLoadingMB] = useState<boolean>(false); 96 + const [error, setError] = useState<string | null>(null); 97 + const [errorOWM, setErrorOWM] = useState<string | null>(null); 98 + const [errorMB, setErrorMB] = useState<string | null>(null); 99 + 100 + // Load stations on component mount 101 + useEffect(() => { 102 + const loadStations = async () => { 103 + try { 104 + setLoading(true); 105 + const response = await fetch(API_ENDPOINTS.FORECAST_STATIONS); 106 + if (!response.ok) { 107 + throw new Error(`Failed to fetch stations: ${response.status}`); 108 + } 109 + const data = await response.json(); 110 + setStations(data.stations); 111 + 112 + // Load last selected station from localStorage 113 + const lastSelected = localStorage.getItem("forecastStation"); 114 + if (lastSelected && data.stations) { 115 + // Verify the station still exists 116 + let stationExists = false; 117 + for (const state in data.stations) { 118 + if (data.stations[state].some((station: Station) => station.id === lastSelected)) { 119 + stationExists = true; 120 + break; 121 + } 122 + } 123 + if (stationExists) { 124 + setSelectedStation(lastSelected); 125 + } 126 + } 127 + } catch (err) { 128 + setError(`Error loading stations: ${err instanceof Error ? err.message : String(err)}`); 129 + console.error("Error loading stations:", err); 130 + } finally { 131 + setLoading(false); 132 + } 133 + }; 134 + 135 + loadStations(); 136 + }, []); 137 + 138 + // Load forecast when station is selected 139 + useEffect(() => { 140 + const loadForecast = async () => { 141 + if (!selectedStation) return; 142 + 143 + try { 144 + setLoading(true); 145 + setError(null); 146 + 147 + // Save selected station to localStorage 148 + localStorage.setItem("forecastStation", selectedStation); 149 + 150 + const response = await fetch(`${API_ENDPOINTS.FORECAST_DATA}&stationId=${selectedStation}`); 151 + if (!response.ok) { 152 + throw new Error(`Failed to fetch forecast: ${response.status}`); 153 + } 154 + const data = await response.json(); 155 + setForecastData(data.forecast || []); 156 + } catch (err) { 157 + setError(`Error loading forecast: ${err instanceof Error ? err.message : String(err)}`); 158 + console.error("Error loading forecast:", err); 159 + } finally { 160 + setLoading(false); 161 + } 162 + }; 163 + 164 + const loadOpenWeather = async () => { 165 + if (!selectedStation) return; 166 + 167 + try { 168 + setLoadingOWM(true); 169 + setErrorOWM(null); 170 + 171 + const response = await fetch(`${API_ENDPOINTS.FORECAST_OPENWEATHER}&stationId=${selectedStation}`); 172 + if (!response.ok) { 173 + throw new Error(`Failed to fetch OpenWeather forecast: ${response.status}`); 174 + } 175 + const data = await response.json(); 176 + setOpenWeatherData(data.forecast || []); 177 + } catch (err) { 178 + setErrorOWM(`Error loading OpenWeather forecast: ${err instanceof Error ? err.message : String(err)}`); 179 + console.error("Error loading OpenWeather forecast:", err); 180 + } finally { 181 + setLoadingOWM(false); 182 + } 183 + }; 184 + 185 + const loadMeteoblue = async () => { 186 + if (!selectedStation) return; 187 + 188 + try { 189 + setLoadingMB(true); 190 + setErrorMB(null); 191 + 192 + const response = await fetch(`${API_ENDPOINTS.FORECAST_METEOBLUE}&stationId=${selectedStation}`); 193 + if (!response.ok) { 194 + throw new Error(`Failed to fetch Meteoblue forecast: ${response.status}`); 195 + } 196 + const data = await response.json(); 197 + setMeteoblueData(data.forecast || []); 198 + } catch (err) { 199 + setErrorMB(`Error loading Meteoblue forecast: ${err instanceof Error ? err.message : String(err)}`); 200 + console.error("Error loading Meteoblue forecast:", err); 201 + } finally { 202 + setLoadingMB(false); 203 + } 204 + }; 205 + 206 + loadForecast(); 207 + loadOpenWeather(); 208 + loadMeteoblue(); 209 + }, [selectedStation]); 210 + 211 + // Group forecast data by day 212 + const groupedForecast = forecastData.reduce((acc: Record<string, ForecastDataPoint[]>, point) => { 213 + const date = new Date(point.time); 214 + const day = date.toLocaleDateString("de-DE", { 215 + weekday: "short", 216 + day: "2-digit", 217 + month: "2-digit" 218 + }); 219 + 220 + if (!acc[day]) { 221 + acc[day] = []; 222 + } 223 + acc[day].push(point); 224 + return acc; 225 + }, {}); 226 + 227 + // Calculate daily averages/max/min 228 + const dailyForecast = Object.entries(groupedForecast).map(([day, points]) => { 229 + const temperatures = points 230 + .map(p => p.temperature) 231 + .filter(t => t !== null) as number[]; 232 + const precipitations = points 233 + .map(p => p.precipitation) 234 + .filter(p => p !== null) as number[]; 235 + const windSpeeds = points 236 + .map(p => p.windSpeed) 237 + .filter(w => w !== null && w !== undefined) as number[]; 238 + 239 + return { 240 + day, 241 + maxTemp: temperatures.length > 0 ? Math.max(...temperatures) : null, 242 + minTemp: temperatures.length > 0 ? Math.min(...temperatures) : null, 243 + avgTemp: temperatures.length > 0 ? 244 + temperatures.reduce((sum, temp) => sum + temp, 0) / temperatures.length : null, 245 + totalPrecip: precipitations.length > 0 ? 246 + precipitations.reduce((sum, precip) => sum + precip, 0) : null, 247 + avgWind: windSpeeds.length > 0 ? 248 + windSpeeds.reduce((sum, wind) => sum + wind, 0) / windSpeeds.length : null, 249 + maxWind: windSpeeds.length > 0 ? Math.max(...windSpeeds) : null 250 + }; 251 + }); 252 + 253 + return ( 254 + <div className="w-full"> 255 + <h1 className="text-2xl font-bold mb-6">{t("tabs.forecast", "Prognose")}</h1> 256 + 257 + {/* Station selection dropdown */} 258 + <div className="mb-6"> 259 + <label htmlFor="station-select" className="block text-sm font-medium mb-2"> 260 + {t("forecast.selectStation", "Wetterstation auswählen")} 261 + </label> 262 + <select 263 + id="station-select" 264 + value={selectedStation} 265 + onChange={(e) => setSelectedStation(e.target.value)} 266 + className="w-full p-2 border border-gray-300 dark:border-neutral-700 rounded bg-white dark:bg-neutral-800 text-gray-900 dark:text-gray-100" 267 + disabled={loading} 268 + > 269 + <option value="">{t("forecast.selectPlaceholder", "Station auswählen...")}</option> 270 + {Object.entries(stations).map(([state, stateStations]) => ( 271 + <optgroup key={state} label={state}> 272 + {stateStations.map((station) => ( 273 + <option key={station.id} value={station.id}> 274 + {station.name} 275 + </option> 276 + ))} 277 + </optgroup> 278 + ))} 279 + </select> 280 + </div> 281 + 282 + {/* Loading and error states */} 283 + {loading && ( 284 + <div className="text-center py-8"> 285 + <div className="inline-block animate-spin rounded-full h-8 w-8 border-t-2 border-b-2 border-blue-500"></div> 286 + <p className="mt-2">{t("statuses.loading")}</p> 287 + </div> 288 + )} 289 + 290 + {error && ( 291 + <div className="bg-red-100 dark:bg-red-900 border border-red-400 dark:border-red-700 text-red-700 dark:text-red-200 px-4 py-3 rounded mb-6"> 292 + <p>{error}</p> 293 + </div> 294 + )} 295 + 296 + {/* Geosphere Forecast */} 297 + {dailyForecast.length > 0 && ( 298 + <div className="mb-8"> 299 + <h2 className="text-xl font-semibold mb-4">🇦🇹 Geosphere Austria (~2.5 Tage)</h2> 300 + <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4"> 301 + {dailyForecast.map((dayData, index) => ( 302 + <div 303 + key={index} 304 + className="border border-gray-200 dark:border-neutral-700 rounded-lg p-5 bg-white dark:bg-neutral-800 shadow-sm" 305 + > 306 + <h3 className="font-semibold text-center mb-3">{dayData.day}</h3> 307 + 308 + <div className="space-y-2"> 309 + {dayData.maxTemp !== null && ( 310 + <div className="flex justify-between"> 311 + <span className="text-gray-600 dark:text-gray-300 text-sm"> 312 + {t("forecast.maxTemp", "Max")} 313 + </span> 314 + <span className="font-medium text-red-600 dark:text-red-400"> 315 + {dayData.maxTemp.toFixed(1)}°C 316 + </span> 317 + </div> 318 + )} 319 + 320 + {dayData.minTemp !== null && ( 321 + <div className="flex justify-between"> 322 + <span className="text-gray-600 dark:text-gray-300 text-sm"> 323 + {t("forecast.minTemp", "Min")} 324 + </span> 325 + <span className="font-medium text-blue-600 dark:text-blue-400"> 326 + {dayData.minTemp.toFixed(1)}°C 327 + </span> 328 + </div> 329 + )} 330 + 331 + {dayData.avgTemp !== null && ( 332 + <div className="flex justify-between"> 333 + <span className="text-gray-600 dark:text-gray-300 text-sm"> 334 + {t("forecast.avgTemp", "Ø")} 335 + </span> 336 + <span className="font-medium text-gray-900 dark:text-gray-100"> 337 + {dayData.avgTemp.toFixed(1)}°C 338 + </span> 339 + </div> 340 + )} 341 + 342 + {dayData.totalPrecip !== null && dayData.totalPrecip > 0 && ( 343 + <div className="mt-3 pt-3 border-t border-gray-200 dark:border-neutral-700"> 344 + <div className="flex justify-between items-center"> 345 + <span className="text-gray-600 dark:text-gray-300 text-sm flex items-center gap-1"> 346 + <span>💧</span> 347 + <span>{t("forecast.precipitation", "Niederschlag")}</span> 348 + </span> 349 + <span className="font-medium text-blue-600 dark:text-blue-400 whitespace-nowrap ml-2"> 350 + {dayData.totalPrecip.toFixed(1)} mm 351 + </span> 352 + </div> 353 + </div> 354 + )} 355 + 356 + {dayData.avgWind !== null && ( 357 + <div className="mt-3 pt-3 border-t border-gray-200 dark:border-neutral-700"> 358 + <div className="flex justify-between items-center"> 359 + <span className="text-gray-600 dark:text-gray-300 text-sm flex items-center gap-1"> 360 + <span>💨</span> 361 + <span>{t("forecast.wind", "Wind")}</span> 362 + </span> 363 + <span className="font-medium text-gray-900 dark:text-gray-100 whitespace-nowrap ml-2"> 364 + {dayData.avgWind.toFixed(1)} km/h 365 + </span> 366 + </div> 367 + </div> 368 + )} 369 + </div> 370 + </div> 371 + ))} 372 + </div> 373 + </div> 374 + )} 375 + 376 + {selectedStation && dailyForecast.length === 0 && !loading && !error && ( 377 + <div className="text-center py-8 text-gray-500 dark:text-gray-400"> 378 + <p>{t("forecast.noData", "Keine Prognosedaten verfügbar")}</p> 379 + </div> 380 + )} 381 + 382 + {/* OpenWeatherMap Forecast */} 383 + {loadingOWM && ( 384 + <div className="text-center py-8"> 385 + <div className="inline-block animate-spin rounded-full h-8 w-8 border-t-2 border-b-2 border-blue-500"></div> 386 + <p className="mt-2">{t("statuses.loading")}</p> 387 + </div> 388 + )} 389 + 390 + {errorOWM && ( 391 + <div className="bg-yellow-100 dark:bg-yellow-900 border border-yellow-400 dark:border-yellow-700 text-yellow-700 dark:text-yellow-200 px-4 py-3 rounded mb-6"> 392 + <p className="font-semibold mb-1">⚠️ OpenWeatherMap Prognose nicht verfügbar</p> 393 + <p className="text-sm">{errorOWM}</p> 394 + <p className="text-xs mt-2"> 395 + 💡 Tipp: Neue API-Keys brauchen 10-30 Minuten zur Aktivierung. 396 + Prüfe auch, ob du die Bestätigungs-E-Mail von OpenWeatherMap erhalten hast. 397 + </p> 398 + </div> 399 + )} 400 + 401 + {openWeatherData.length > 0 && ( 402 + <div className="mb-8"> 403 + <h2 className="text-xl font-semibold mb-4">🌍 OpenWeatherMap (5 Tage)</h2> 404 + <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4"> 405 + {openWeatherData.map((dayData, index) => { 406 + const date = new Date(dayData.date); 407 + const dayLabel = date.toLocaleDateString("de-DE", { 408 + weekday: "short", 409 + day: "2-digit", 410 + month: "2-digit" 411 + }); 412 + 413 + return ( 414 + <div 415 + key={index} 416 + className="border border-gray-200 dark:border-neutral-700 rounded-lg p-5 bg-white dark:bg-neutral-800 shadow-sm" 417 + > 418 + <h3 className="font-semibold text-center mb-3">{dayLabel}</h3> 419 + 420 + <div className="space-y-2"> 421 + {dayData.tempMax !== null && ( 422 + <div className="flex justify-between"> 423 + <span className="text-gray-600 dark:text-gray-300 text-sm"> 424 + {t("forecast.maxTemp", "Max")} 425 + </span> 426 + <span className="font-medium text-red-600 dark:text-red-400"> 427 + {dayData.tempMax.toFixed(1)}°C 428 + </span> 429 + </div> 430 + )} 431 + 432 + {dayData.tempMin !== null && ( 433 + <div className="flex justify-between"> 434 + <span className="text-gray-600 dark:text-gray-300 text-sm"> 435 + {t("forecast.minTemp", "Min")} 436 + </span> 437 + <span className="font-medium text-blue-600 dark:text-blue-400"> 438 + {dayData.tempMin.toFixed(1)}°C 439 + </span> 440 + </div> 441 + )} 442 + 443 + {dayData.tempDay !== null && ( 444 + <div className="flex justify-between"> 445 + <span className="text-gray-600 dark:text-gray-300 text-sm"> 446 + {t("forecast.dayTemp", "Tag")} 447 + </span> 448 + <span className="font-medium text-gray-900 dark:text-gray-100"> 449 + {dayData.tempDay.toFixed(1)}°C 450 + </span> 451 + </div> 452 + )} 453 + 454 + {dayData.precipitation > 0 && ( 455 + <div className="mt-3 pt-3 border-t border-gray-200 dark:border-neutral-700"> 456 + <div className="flex justify-between items-center"> 457 + <span className="text-gray-600 dark:text-gray-300 text-sm flex items-center gap-1"> 458 + <span>💧</span> 459 + <span>{t("forecast.precipitation", "Niederschlag")}</span> 460 + </span> 461 + <span className="font-medium text-blue-600 dark:text-blue-400 whitespace-nowrap ml-2"> 462 + {dayData.precipitation.toFixed(1)} mm 463 + </span> 464 + </div> 465 + {dayData.pop !== null && ( 466 + <div className="text-xs text-gray-500 dark:text-gray-400 mt-1 text-right"> 467 + {(dayData.pop * 100).toFixed(0)}% Wahrscheinlichkeit 468 + </div> 469 + )} 470 + </div> 471 + )} 472 + 473 + {dayData.windSpeed !== null && ( 474 + <div className="mt-3 pt-3 border-t border-gray-200 dark:border-neutral-700"> 475 + <div className="flex justify-between items-center"> 476 + <span className="text-gray-600 dark:text-gray-300 text-sm flex items-center gap-1"> 477 + <span>💨</span> 478 + <span>{t("forecast.wind", "Wind")}</span> 479 + </span> 480 + <span className="font-medium text-gray-900 dark:text-gray-100 whitespace-nowrap ml-2"> 481 + {dayData.windSpeed.toFixed(1)} km/h 482 + </span> 483 + </div> 484 + {dayData.windGust !== null && ( 485 + <div className="text-xs text-gray-500 dark:text-gray-400 mt-1 text-right"> 486 + Böen: {dayData.windGust.toFixed(1)} km/h 487 + </div> 488 + )} 489 + </div> 490 + )} 491 + 492 + {dayData.weather && ( 493 + <div className="mt-3 pt-3 border-t border-gray-200 dark:border-neutral-700 text-center"> 494 + <div className="text-2xl mb-1"> 495 + {dayData.weather.icon && ( 496 + <img 497 + src={`https://openweathermap.org/img/wn/${dayData.weather.icon}@2x.png`} 498 + alt={dayData.weather.description} 499 + className="inline-block w-12 h-12" 500 + /> 501 + )} 502 + </div> 503 + <div className="text-xs text-gray-600 dark:text-gray-400"> 504 + {dayData.weather.description} 505 + </div> 506 + </div> 507 + )} 508 + </div> 509 + </div> 510 + ); 511 + })} 512 + </div> 513 + </div> 514 + )} 515 + 516 + {/* Meteoblue Forecast */} 517 + {loadingMB && ( 518 + <div className="text-center py-8"> 519 + <div className="inline-block animate-spin rounded-full h-8 w-8 border-t-2 border-b-2 border-blue-500"></div> 520 + <p className="mt-2">{t("statuses.loading")}</p> 521 + </div> 522 + )} 523 + 524 + {errorMB && ( 525 + <div className="bg-yellow-100 dark:bg-yellow-900 border border-yellow-400 dark:border-yellow-700 text-yellow-700 dark:text-yellow-200 px-4 py-3 rounded mb-6"> 526 + <p className="font-semibold mb-1">⚠️ Meteoblue Prognose nicht verfügbar</p> 527 + <p className="text-sm">{errorMB}</p> 528 + <p className="text-xs mt-2"> 529 + 💡 Tipp: Registriere dich kostenlos auf meteoblue.com und bestätige die nicht-kommerzielle Nutzung. 530 + </p> 531 + </div> 532 + )} 533 + 534 + {meteoblueData.length > 0 && selectedStation && ( 535 + <div className="mb-8"> 536 + <h2 className="text-xl font-semibold mb-4">🇨🇭 Meteoblue (7 Tage)</h2> 537 + <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4"> 538 + {meteoblueData.map((dayData, index) => { 539 + const date = new Date(dayData.date); 540 + const dayLabel = date.toLocaleDateString("de-DE", { 541 + weekday: "short", 542 + day: "2-digit", 543 + month: "2-digit" 544 + }); 545 + 546 + return ( 547 + <div 548 + key={index} 549 + className="border border-gray-200 dark:border-neutral-700 rounded-lg p-5 bg-white dark:bg-neutral-800 shadow-sm" 550 + > 551 + <h3 className="font-semibold text-center mb-3">{dayLabel}</h3> 552 + 553 + <div className="space-y-2"> 554 + {dayData.tempMax !== null && ( 555 + <div className="flex justify-between"> 556 + <span className="text-gray-600 dark:text-gray-300 text-sm"> 557 + {t("forecast.maxTemp", "Max")} 558 + </span> 559 + <span className="font-medium text-red-600 dark:text-red-400"> 560 + {dayData.tempMax.toFixed(1)}°C 561 + </span> 562 + </div> 563 + )} 564 + 565 + {dayData.tempMin !== null && ( 566 + <div className="flex justify-between"> 567 + <span className="text-gray-600 dark:text-gray-300 text-sm"> 568 + {t("forecast.minTemp", "Min")} 569 + </span> 570 + <span className="font-medium text-blue-600 dark:text-blue-400"> 571 + {dayData.tempMin.toFixed(1)}°C 572 + </span> 573 + </div> 574 + )} 575 + 576 + {dayData.tempMean !== null && ( 577 + <div className="flex justify-between"> 578 + <span className="text-gray-600 dark:text-gray-300 text-sm"> 579 + {t("forecast.avgTemp", "Ø")} 580 + </span> 581 + <span className="font-medium text-gray-900 dark:text-gray-100"> 582 + {dayData.tempMean.toFixed(1)}°C 583 + </span> 584 + </div> 585 + )} 586 + 587 + {dayData.precipitation > 0 && ( 588 + <div className="mt-3 pt-3 border-t border-gray-200 dark:border-neutral-700"> 589 + <div className="flex justify-between items-center"> 590 + <span className="text-gray-600 dark:text-gray-300 text-sm flex items-center gap-1"> 591 + <span>💧</span> 592 + <span>{t("forecast.precipitation", "Niederschlag")}</span> 593 + </span> 594 + <span className="font-medium text-blue-600 dark:text-blue-400 whitespace-nowrap ml-2"> 595 + {dayData.precipitation.toFixed(1)} mm 596 + </span> 597 + </div> 598 + </div> 599 + )} 600 + 601 + {dayData.windSpeed !== null && ( 602 + <div className="mt-3 pt-3 border-t border-gray-200 dark:border-neutral-700"> 603 + <div className="flex justify-between items-center"> 604 + <span className="text-gray-600 dark:text-gray-300 text-sm flex items-center gap-1"> 605 + <span>💨</span> 606 + <span>{t("forecast.wind", "Wind")}</span> 607 + </span> 608 + <span className="font-medium text-gray-900 dark:text-gray-100 whitespace-nowrap ml-2"> 609 + {dayData.windSpeed.toFixed(1)} km/h 610 + </span> 611 + </div> 612 + {dayData.windGust !== null && ( 613 + <div className="text-xs text-gray-500 dark:text-gray-400 mt-1 text-right"> 614 + Böen: {dayData.windGust.toFixed(1)} km/h 615 + </div> 616 + )} 617 + </div> 618 + )} 619 + 620 + {dayData.pictocode !== null && ( 621 + <div className="mt-3 pt-3 border-t border-gray-200 dark:border-neutral-700 text-center"> 622 + <div className="mb-1"> 623 + <img 624 + src={`https://static.meteoblue.com/assets/images/picto/${dayData.pictocode}_iday.svg`} 625 + alt={`Weather code ${dayData.pictocode}`} 626 + className="inline-block w-16 h-16" 627 + onError={(e) => { 628 + // Fallback to emoji if image fails 629 + const target = e.target as HTMLImageElement; 630 + const parent = target.parentElement; 631 + if (parent && dayData.pictocode !== null) { 632 + parent.innerHTML = `<div class="text-4xl">${getWeatherEmoji(dayData.pictocode)}</div>`; 633 + } 634 + }} 635 + /> 636 + </div> 637 + <div className="text-xs text-gray-600 dark:text-gray-300"> 638 + {t(`forecast.weather.${dayData.pictocode}`, t("forecast.weather.unknown", "Unknown"))} 639 + </div> 640 + </div> 641 + )} 642 + </div> 643 + </div> 644 + ); 645 + })} 646 + </div> 647 + 648 + {/* Meteoblue Meteogram */} 649 + <div className="mt-6"> 650 + <h3 className="text-lg font-semibold mb-3">📊 Meteogramm (14 Tage)</h3> 651 + <div className="border border-gray-200 dark:border-neutral-700 rounded-lg p-4 bg-white dark:bg-neutral-800 shadow-sm overflow-x-auto"> 652 + {(() => { 653 + const station = Object.values(stations).flat().find(s => s.id === selectedStation); 654 + if (!station) return null; 655 + 656 + // Use API route to get meteogram with server-side API key 657 + const meteogramUrl = `/api/forecast?action=meteogram&stationId=${selectedStation}`; 658 + 659 + return ( 660 + <img 661 + src={meteogramUrl} 662 + alt={`Meteogramm für ${station.name}`} 663 + className="w-full h-auto" 664 + onError={(e) => { 665 + const target = e.target as HTMLImageElement; 666 + target.style.display = 'none'; 667 + const parent = target.parentElement; 668 + if (parent) { 669 + parent.innerHTML = '<p class="text-center text-gray-500 dark:text-gray-400 py-4">Meteogramm konnte nicht geladen werden. Prüfe deinen Meteoblue API-Key.</p>'; 670 + } 671 + }} 672 + /> 673 + ); 674 + })()} 675 + </div> 676 + </div> 677 + </div> 678 + )} 679 + </div> 680 + ); 681 + }
+6
src/constants.js
··· 26 26 // Dashboard/server-side range statistics 27 27 STATISTICS_RANGE: '/api/statistics/range', 28 28 STATISTICS_CHANNELS: '/api/statistics/channels', 29 + 30 + // Forecast endpoints 31 + FORECAST_STATIONS: '/api/forecast?action=stations', 32 + FORECAST_DATA: '/api/forecast?action=forecast', 33 + FORECAST_OPENWEATHER: '/api/forecast?action=openweather', 34 + FORECAST_METEOBLUE: '/api/forecast?action=meteoblue', 29 35 };
+43 -1
src/locales/de/common.json
··· 3 3 "realtime": "Echtzeit", 4 4 "graphics": "Grafik", 5 5 "saved": "Gespeicherte Daten", 6 - "statistics": "Statistik" 6 + "statistics": "Statistik", 7 + "forecast": "Prognose" 7 8 }, 8 9 "statuses": { 9 10 "lastUpdate": "Letzte Aktualisierung:", ··· 152 153 "sortByValue": "Wert", 153 154 "sortAsc": "ASC", 154 155 "sortDesc": "DESC" 156 + }, 157 + "forecast": { 158 + "selectStation": "Wetterstation auswählen", 159 + "selectPlaceholder": "Station auswählen...", 160 + "maxTemp": "Max", 161 + "minTemp": "Min", 162 + "avgTemp": "Ø", 163 + "dayTemp": "Tag", 164 + "precipitation": "Niederschlag", 165 + "wind": "Wind", 166 + "noData": "Keine Prognosedaten verfügbar", 167 + "weather": { 168 + "1": "Sonnig", 169 + "2": "Heiter", 170 + "3": "Heiter", 171 + "4": "Leicht bewölkt", 172 + "5": "Leicht bewölkt", 173 + "6": "Leicht bewölkt", 174 + "7": "Teilweise bewölkt", 175 + "8": "Teilweise bewölkt", 176 + "9": "Teilweise bewölkt", 177 + "10": "Bewölkt", 178 + "11": "Nebel", 179 + "12": "Nebel", 180 + "13": "Nebel", 181 + "14": "Nebel", 182 + "15": "Regen möglich", 183 + "16": "Regen", 184 + "17": "Gewitter", 185 + "18": "Gewitter", 186 + "19": "Schnee", 187 + "20": "Schneeregen", 188 + "21": "Regen", 189 + "22": "Schnee", 190 + "23": "Gewitter möglich", 191 + "24": "Gewitter mit Hagel", 192 + "25": "Leichter Regen", 193 + "26": "Regen", 194 + "27": "Starker Regen", 195 + "unknown": "Unbekannt" 196 + } 155 197 } 156 198 }
+43 -1
src/locales/en/common.json
··· 3 3 "realtime": "Realtime", 4 4 "graphics": "Graphics", 5 5 "saved": "Saved Data", 6 - "statistics": "Statistics" 6 + "statistics": "Statistics", 7 + "forecast": "Forecast" 7 8 }, 8 9 "statuses": { 9 10 "lastUpdate": "Last update:", ··· 152 153 "sortByValue": "Value", 153 154 "sortAsc": "ASC", 154 155 "sortDesc": "DESC" 156 + }, 157 + "forecast": { 158 + "selectStation": "Select weather station", 159 + "selectPlaceholder": "Select station...", 160 + "maxTemp": "Max", 161 + "minTemp": "Min", 162 + "avgTemp": "Avg", 163 + "dayTemp": "Day", 164 + "precipitation": "Precipitation", 165 + "wind": "Wind", 166 + "noData": "No forecast data available", 167 + "weather": { 168 + "1": "Sunny", 169 + "2": "Clear", 170 + "3": "Clear", 171 + "4": "Partly cloudy", 172 + "5": "Partly cloudy", 173 + "6": "Partly cloudy", 174 + "7": "Partly cloudy", 175 + "8": "Partly cloudy", 176 + "9": "Partly cloudy", 177 + "10": "Cloudy", 178 + "11": "Fog", 179 + "12": "Fog", 180 + "13": "Fog", 181 + "14": "Fog", 182 + "15": "Rain possible", 183 + "16": "Rain", 184 + "17": "Thunderstorms", 185 + "18": "Thunderstorms", 186 + "19": "Snow", 187 + "20": "Sleet", 188 + "21": "Rain", 189 + "22": "Snow", 190 + "23": "Thunderstorms possible", 191 + "24": "Thunderstorms with hail", 192 + "25": "Light rain", 193 + "26": "Rain", 194 + "27": "Heavy rain", 195 + "unknown": "Unknown" 196 + } 155 197 } 156 198 }
+71 -71
temp-minmax-data.json
··· 1 1 { 2 - "date": "2025-09-27", 2 + "date": "2025-11-02", 3 3 "sensors": { 4 4 "indoor": { 5 - "min": 22, 6 - "max": 22.2, 7 - "minTime": "2025-09-27T16:46:45.053Z", 8 - "maxTime": "2025-09-27T15:26:45.568Z" 5 + "min": 21.3, 6 + "max": 21.4, 7 + "minTime": "2025-11-02T13:47:07.767Z", 8 + "maxTime": "2025-11-02T13:19:45.681Z" 9 9 }, 10 10 "outdoor": { 11 - "min": 14.1, 12 - "max": 16.9, 13 - "minTime": "2025-09-27T17:06:45.078Z", 14 - "maxTime": "2025-09-27T15:26:45.568Z" 11 + "min": 14.8, 12 + "max": 17.3, 13 + "minTime": "2025-11-02T15:06:36.784Z", 14 + "maxTime": "2025-11-02T13:19:45.681Z" 15 15 }, 16 16 "temp_and_humidity_ch1": { 17 - "min": 18, 18 - "max": 18.2, 19 - "minTime": "2025-09-27T16:56:45.030Z", 20 - "maxTime": "2025-09-27T15:26:45.568Z" 17 + "min": 16.3, 18 + "max": 16.4, 19 + "minTime": "2025-11-02T13:19:45.681Z", 20 + "maxTime": "2025-11-02T13:28:28.497Z" 21 21 }, 22 22 "temp_and_humidity_ch2": { 23 - "min": 21.5, 24 - "max": 21.5, 25 - "minTime": "2025-09-27T15:26:45.568Z", 26 - "maxTime": "2025-09-27T15:26:45.568Z" 23 + "min": 20.6, 24 + "max": 20.8, 25 + "minTime": "2025-11-02T13:43:27.628Z", 26 + "maxTime": "2025-11-02T14:21:49.969Z" 27 27 }, 28 28 "temp_and_humidity_ch3": { 29 - "min": 18.4, 30 - "max": 19, 31 - "minTime": "2025-09-27T17:21:45.068Z", 32 - "maxTime": "2025-09-27T15:26:45.568Z" 29 + "min": 15.6, 30 + "max": 16.2, 31 + "minTime": "2025-11-02T15:06:36.784Z", 32 + "maxTime": "2025-11-02T13:19:45.681Z" 33 33 }, 34 34 "temp_and_humidity_ch5": { 35 - "min": 21.3, 36 - "max": 21.8, 37 - "minTime": "2025-09-27T16:56:45.030Z", 38 - "maxTime": "2025-09-27T15:26:45.568Z" 35 + "min": 20.7, 36 + "max": 20.9, 37 + "minTime": "2025-11-02T14:31:49.630Z", 38 + "maxTime": "2025-11-02T13:19:45.681Z" 39 39 }, 40 40 "temp_and_humidity_ch6": { 41 - "min": 20.2, 42 - "max": 20.3, 43 - "minTime": "2025-09-27T15:26:45.568Z", 44 - "maxTime": "2025-09-27T16:01:45.162Z" 41 + "min": 18.7, 42 + "max": 18.7, 43 + "minTime": "2025-11-02T13:19:45.681Z", 44 + "maxTime": "2025-11-02T13:19:45.681Z" 45 45 }, 46 46 "temp_and_humidity_ch7": { 47 - "min": 15.8, 48 - "max": 18.6, 49 - "minTime": "2025-09-27T17:16:45.058Z", 50 - "maxTime": "2025-09-27T15:26:45.568Z" 47 + "min": 14.3, 48 + "max": 15.7, 49 + "minTime": "2025-11-02T15:06:36.784Z", 50 + "maxTime": "2025-11-02T13:19:45.681Z" 51 51 }, 52 52 "temp_and_humidity_ch8": { 53 - "min": 19.9, 54 - "max": 20.1, 55 - "minTime": "2025-09-27T17:21:45.068Z", 56 - "maxTime": "2025-09-27T15:26:45.568Z" 53 + "min": 20.4, 54 + "max": 20.6, 55 + "minTime": "2025-11-02T14:26:49.734Z", 56 + "maxTime": "2025-11-02T13:19:45.681Z" 57 57 } 58 58 }, 59 59 "humidity": { 60 60 "indoor": { 61 61 "min": 60, 62 62 "max": 62, 63 - "minTime": "2025-09-27T15:26:45.568Z", 64 - "maxTime": "2025-09-27T17:01:45.060Z" 63 + "minTime": "2025-11-02T13:19:45.681Z", 64 + "maxTime": "2025-11-02T14:26:49.734Z" 65 65 }, 66 66 "outdoor": { 67 - "min": 75, 68 - "max": 90, 69 - "minTime": "2025-09-27T15:51:45.200Z", 70 - "maxTime": "2025-09-27T16:56:45.030Z" 67 + "min": 83, 68 + "max": 95, 69 + "minTime": "2025-11-02T13:38:27.577Z", 70 + "maxTime": "2025-11-02T15:06:36.784Z" 71 71 }, 72 72 "temp_and_humidity_ch1": { 73 - "min": 68, 74 - "max": 68, 75 - "minTime": "2025-09-27T15:26:45.568Z", 76 - "maxTime": "2025-09-27T15:26:45.568Z" 73 + "min": 69, 74 + "max": 69, 75 + "minTime": "2025-11-02T13:19:45.681Z", 76 + "maxTime": "2025-11-02T13:19:45.681Z" 77 77 }, 78 78 "temp_and_humidity_ch2": { 79 - "min": 63, 80 - "max": 65, 81 - "minTime": "2025-09-27T15:26:45.568Z", 82 - "maxTime": "2025-09-27T17:01:45.060Z" 79 + "min": 64, 80 + "max": 68, 81 + "minTime": "2025-11-02T13:19:45.681Z", 82 + "maxTime": "2025-11-02T14:26:49.734Z" 83 83 }, 84 84 "temp_and_humidity_ch3": { 85 - "min": 65, 86 - "max": 67, 87 - "minTime": "2025-09-27T15:31:45.184Z", 88 - "maxTime": "2025-09-27T16:26:45.935Z" 85 + "min": 79, 86 + "max": 80, 87 + "minTime": "2025-11-02T13:19:45.681Z", 88 + "maxTime": "2025-11-02T14:41:49.852Z" 89 89 }, 90 90 "temp_and_humidity_ch5": { 91 - "min": 60, 92 - "max": 62, 93 - "minTime": "2025-09-27T16:21:45.240Z", 94 - "maxTime": "2025-09-27T15:26:45.568Z" 91 + "min": 69, 92 + "max": 69, 93 + "minTime": "2025-11-02T13:19:45.681Z", 94 + "maxTime": "2025-11-02T13:19:45.681Z" 95 95 }, 96 96 "temp_and_humidity_ch6": { 97 - "min": 61, 98 - "max": 62, 99 - "minTime": "2025-09-27T15:26:45.568Z", 100 - "maxTime": "2025-09-27T16:51:45.159Z" 97 + "min": 69, 98 + "max": 69, 99 + "minTime": "2025-11-02T13:19:45.681Z", 100 + "maxTime": "2025-11-02T13:19:45.681Z" 101 101 }, 102 102 "temp_and_humidity_ch7": { 103 - "min": 71, 104 - "max": 80, 105 - "minTime": "2025-09-27T15:26:45.568Z", 106 - "maxTime": "2025-09-27T17:01:45.060Z" 103 + "min": 94, 104 + "max": 97, 105 + "minTime": "2025-11-02T13:38:27.577Z", 106 + "maxTime": "2025-11-02T14:51:36.541Z" 107 107 }, 108 108 "temp_and_humidity_ch8": { 109 - "min": 62, 110 - "max": 62, 111 - "minTime": "2025-09-27T15:26:45.568Z", 112 - "maxTime": "2025-09-27T15:26:45.568Z" 109 + "min": 68, 110 + "max": 68, 111 + "minTime": "2025-11-02T13:19:45.681Z", 112 + "maxTime": "2025-11-02T13:19:45.681Z" 113 113 } 114 114 } 115 115 }
+22 -6
tsconfig.json
··· 1 1 { 2 2 "compilerOptions": { 3 3 "target": "ES2017", 4 - "lib": ["dom", "dom.iterable", "esnext"], 4 + "lib": [ 5 + "dom", 6 + "dom.iterable", 7 + "esnext" 8 + ], 5 9 "allowJs": true, 6 10 "skipLibCheck": true, 7 11 "strict": true, ··· 12 16 "baseUrl": ".", 13 17 "resolveJsonModule": true, 14 18 "isolatedModules": true, 15 - "jsx": "preserve", 19 + "jsx": "react-jsx", 16 20 "incremental": true, 17 21 "plugins": [ 18 22 { ··· 20 24 } 21 25 ], 22 26 "paths": { 23 - "@/*": ["./src/*"], 24 - "eco": ["./eco.ts"] 27 + "@/*": [ 28 + "./src/*" 29 + ], 30 + "eco": [ 31 + "./eco.ts" 32 + ] 25 33 } 26 34 }, 27 - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 28 - "exclude": ["node_modules"] 35 + "include": [ 36 + "next-env.d.ts", 37 + "**/*.ts", 38 + "**/*.tsx", 39 + ".next/types/**/*.ts", 40 + ".next/dev/types/**/*.ts" 41 + ], 42 + "exclude": [ 43 + "node_modules" 44 + ] 29 45 }