Procedurally generates a radio weather report

Compare changes

Choose any two refs to compare.

+44
.github/workflows/test.yml
··· 1 + name: Unit tests 2 + 3 + on: 4 + push: 5 + branches: [ master ] 6 + pull_request: 7 + branches: [ master ] 8 + 9 + jobs: 10 + 11 + npm_test: 12 + name: Unit tests 13 + runs-on: ubuntu-latest 14 + timeout-minutes: 20 15 + strategy: 16 + fail-fast: true 17 + matrix: 18 + nodever: 19 + [ 20 + 'latest', 21 + 'lts/*', 22 + 'lts/hydrogen' 23 + ] 24 + permissions: 25 + contents: read 26 + 27 + steps: 28 + - name: Checkout repository 29 + uses: https://github.com/actions/checkout@v4 30 + 31 + - name: Setup nodejs 32 + uses: https://github.com/actions/setup-node@v4 33 + with: 34 + node-version: "${{ matrix.nodever }}" 35 + check-latest: true 36 + 37 + - name: Install dependencies 38 + run: npm ci 39 + 40 + - name: Build 41 + run: npm run build 42 + 43 + - name: Run tests 44 + run: npm test
+3
.gitignore
··· 102 102 config/config.json5 103 103 distribution/ 104 104 .env 105 + test/*.js* 106 + output.wav 107 + output.mp3
+18
.tangled/workflows/audit.yml
··· 1 + when: 2 + - event: ["push"] 3 + branch: ["master"] 4 + 5 + engine: "nixery" 6 + 7 + dependencies: 8 + nixpkgs: 9 + - nodejs 10 + 11 + steps: 12 + - name: "NPM Audit" 13 + command: "npm audit" 14 + 15 + clone: 16 + skip: false 17 + depth: 3 18 + submodules: false
+24
.tangled/workflows/test.yml
··· 1 + when: 2 + - event: ["push"] 3 + branch: ["master"] 4 + 5 + engine: "nixery" 6 + 7 + dependencies: 8 + nixpkgs: 9 + - nodejs 10 + 11 + steps: 12 + - name: "Install dependencies" 13 + command: "npm ci" 14 + 15 + - name: "tsc" 16 + command: "npm run build && echo 'done.'" 17 + 18 + - name: "tests" 19 + command: "npm test" 20 + 21 + clone: 22 + skip: false 23 + depth: 3 24 + submodules: false
+22
.vscode/launch.json
··· 1 + { 2 + // Use IntelliSense to learn about possible attributes. 3 + // Hover to view descriptions of existing attributes. 4 + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 + "version": "0.2.0", 6 + "configurations": [ 7 + 8 + { 9 + "type": "node", 10 + "request": "launch", 11 + "name": "Launch Program", 12 + "skipFiles": [ 13 + "<node_internals>/**" 14 + ], 15 + "program": "${workspaceFolder}/src/index.ts", 16 + "preLaunchTask": "tsc: build - tsconfig.json", 17 + "outFiles": [ 18 + "${workspaceFolder}/distribution/**/*.js" 19 + ] 20 + } 21 + ] 22 + }
+10 -4
config/config.example.json5
··· 49 49 "hilo 1": { 50 50 "tracks": [ 51 51 "audio/hi_01.flac", 52 - "%cory hi", 52 + "%cory weather.temp.max", 53 53 "audio/lo_01.flac", 54 - "%cory lo" 54 + "%cory weather.temp.min" 55 55 ] 56 56 }, 57 57 "hilo 2": { 58 58 "tracks": [ 59 59 "audio/hi_02.flac", 60 - "%cory hi", 60 + "%cory weather.temp.max", 61 61 "audio/lo_02.flac", 62 - "%cory lo" 62 + "%cory weather.temp.min" 63 63 ] 64 64 }, 65 65 "rain 1": { ··· 114 114 "directory": "audio/voice/cory/", 115 115 "extension": "flac" 116 116 } 117 + }, 118 + "weather": { 119 + // Provide an OpenWeatherMap API key 120 + // https://openweathermap.org/price 121 + "key": "not0a0real0key00281f631aef6ad3a1", 122 + "city": "chicago" 117 123 } 118 124 }
+2346 -46
package-lock.json
··· 1 1 { 2 2 "name": "morning-report", 3 - "version": "0.0.1", 3 + "version": "0.0.5", 4 4 "lockfileVersion": 3, 5 5 "requires": true, 6 6 "packages": { 7 7 "": { 8 8 "name": "morning-report", 9 - "version": "0.0.1", 9 + "version": "0.0.5", 10 10 "license": "MIT", 11 11 "dependencies": { 12 12 "json5": "2.2.3", 13 - "openweathermap-ts": "1.2.10" 13 + "openweather-api-node": "3.1.5" 14 + }, 15 + "bin": { 16 + "morning-report": "distribution/src/index.js" 14 17 }, 15 18 "devDependencies": { 16 - "@types/node": "24.3.0", 17 - "typescript": "5.9.2" 19 + "@types/node": "24.10.1", 20 + "@vitest/coverage-v8": "3.2.4", 21 + "typescript": "5.9.3", 22 + "vitest": "3.2.4" 23 + } 24 + }, 25 + "node_modules/@ampproject/remapping": { 26 + "version": "2.3.0", 27 + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", 28 + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", 29 + "dev": true, 30 + "license": "Apache-2.0", 31 + "dependencies": { 32 + "@jridgewell/gen-mapping": "^0.3.5", 33 + "@jridgewell/trace-mapping": "^0.3.24" 34 + }, 35 + "engines": { 36 + "node": ">=6.0.0" 37 + } 38 + }, 39 + "node_modules/@babel/helper-string-parser": { 40 + "version": "7.27.1", 41 + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", 42 + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", 43 + "dev": true, 44 + "license": "MIT", 45 + "engines": { 46 + "node": ">=6.9.0" 47 + } 48 + }, 49 + "node_modules/@babel/helper-validator-identifier": { 50 + "version": "7.28.5", 51 + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", 52 + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", 53 + "dev": true, 54 + "license": "MIT", 55 + "engines": { 56 + "node": ">=6.9.0" 57 + } 58 + }, 59 + "node_modules/@babel/parser": { 60 + "version": "7.28.5", 61 + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", 62 + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", 63 + "dev": true, 64 + "license": "MIT", 65 + "dependencies": { 66 + "@babel/types": "^7.28.5" 67 + }, 68 + "bin": { 69 + "parser": "bin/babel-parser.js" 70 + }, 71 + "engines": { 72 + "node": ">=6.0.0" 73 + } 74 + }, 75 + "node_modules/@babel/types": { 76 + "version": "7.28.5", 77 + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", 78 + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", 79 + "dev": true, 80 + "license": "MIT", 81 + "dependencies": { 82 + "@babel/helper-string-parser": "^7.27.1", 83 + "@babel/helper-validator-identifier": "^7.28.5" 84 + }, 85 + "engines": { 86 + "node": ">=6.9.0" 87 + } 88 + }, 89 + "node_modules/@bcoe/v8-coverage": { 90 + "version": "1.0.2", 91 + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", 92 + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", 93 + "dev": true, 94 + "license": "MIT", 95 + "engines": { 96 + "node": ">=18" 97 + } 98 + }, 99 + "node_modules/@esbuild/aix-ppc64": { 100 + "version": "0.25.12", 101 + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", 102 + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", 103 + "cpu": [ 104 + "ppc64" 105 + ], 106 + "dev": true, 107 + "license": "MIT", 108 + "optional": true, 109 + "os": [ 110 + "aix" 111 + ], 112 + "engines": { 113 + "node": ">=18" 114 + } 115 + }, 116 + "node_modules/@esbuild/android-arm": { 117 + "version": "0.25.12", 118 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", 119 + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", 120 + "cpu": [ 121 + "arm" 122 + ], 123 + "dev": true, 124 + "license": "MIT", 125 + "optional": true, 126 + "os": [ 127 + "android" 128 + ], 129 + "engines": { 130 + "node": ">=18" 131 + } 132 + }, 133 + "node_modules/@esbuild/android-arm64": { 134 + "version": "0.25.12", 135 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", 136 + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", 137 + "cpu": [ 138 + "arm64" 139 + ], 140 + "dev": true, 141 + "license": "MIT", 142 + "optional": true, 143 + "os": [ 144 + "android" 145 + ], 146 + "engines": { 147 + "node": ">=18" 148 + } 149 + }, 150 + "node_modules/@esbuild/android-x64": { 151 + "version": "0.25.12", 152 + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", 153 + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", 154 + "cpu": [ 155 + "x64" 156 + ], 157 + "dev": true, 158 + "license": "MIT", 159 + "optional": true, 160 + "os": [ 161 + "android" 162 + ], 163 + "engines": { 164 + "node": ">=18" 165 + } 166 + }, 167 + "node_modules/@esbuild/darwin-arm64": { 168 + "version": "0.25.12", 169 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", 170 + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", 171 + "cpu": [ 172 + "arm64" 173 + ], 174 + "dev": true, 175 + "license": "MIT", 176 + "optional": true, 177 + "os": [ 178 + "darwin" 179 + ], 180 + "engines": { 181 + "node": ">=18" 182 + } 183 + }, 184 + "node_modules/@esbuild/darwin-x64": { 185 + "version": "0.25.12", 186 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", 187 + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", 188 + "cpu": [ 189 + "x64" 190 + ], 191 + "dev": true, 192 + "license": "MIT", 193 + "optional": true, 194 + "os": [ 195 + "darwin" 196 + ], 197 + "engines": { 198 + "node": ">=18" 199 + } 200 + }, 201 + "node_modules/@esbuild/freebsd-arm64": { 202 + "version": "0.25.12", 203 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", 204 + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", 205 + "cpu": [ 206 + "arm64" 207 + ], 208 + "dev": true, 209 + "license": "MIT", 210 + "optional": true, 211 + "os": [ 212 + "freebsd" 213 + ], 214 + "engines": { 215 + "node": ">=18" 216 + } 217 + }, 218 + "node_modules/@esbuild/freebsd-x64": { 219 + "version": "0.25.12", 220 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", 221 + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", 222 + "cpu": [ 223 + "x64" 224 + ], 225 + "dev": true, 226 + "license": "MIT", 227 + "optional": true, 228 + "os": [ 229 + "freebsd" 230 + ], 231 + "engines": { 232 + "node": ">=18" 233 + } 234 + }, 235 + "node_modules/@esbuild/linux-arm": { 236 + "version": "0.25.12", 237 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", 238 + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", 239 + "cpu": [ 240 + "arm" 241 + ], 242 + "dev": true, 243 + "license": "MIT", 244 + "optional": true, 245 + "os": [ 246 + "linux" 247 + ], 248 + "engines": { 249 + "node": ">=18" 250 + } 251 + }, 252 + "node_modules/@esbuild/linux-arm64": { 253 + "version": "0.25.12", 254 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", 255 + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", 256 + "cpu": [ 257 + "arm64" 258 + ], 259 + "dev": true, 260 + "license": "MIT", 261 + "optional": true, 262 + "os": [ 263 + "linux" 264 + ], 265 + "engines": { 266 + "node": ">=18" 267 + } 268 + }, 269 + "node_modules/@esbuild/linux-ia32": { 270 + "version": "0.25.12", 271 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", 272 + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", 273 + "cpu": [ 274 + "ia32" 275 + ], 276 + "dev": true, 277 + "license": "MIT", 278 + "optional": true, 279 + "os": [ 280 + "linux" 281 + ], 282 + "engines": { 283 + "node": ">=18" 284 + } 285 + }, 286 + "node_modules/@esbuild/linux-loong64": { 287 + "version": "0.25.12", 288 + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", 289 + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", 290 + "cpu": [ 291 + "loong64" 292 + ], 293 + "dev": true, 294 + "license": "MIT", 295 + "optional": true, 296 + "os": [ 297 + "linux" 298 + ], 299 + "engines": { 300 + "node": ">=18" 301 + } 302 + }, 303 + "node_modules/@esbuild/linux-mips64el": { 304 + "version": "0.25.12", 305 + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", 306 + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", 307 + "cpu": [ 308 + "mips64el" 309 + ], 310 + "dev": true, 311 + "license": "MIT", 312 + "optional": true, 313 + "os": [ 314 + "linux" 315 + ], 316 + "engines": { 317 + "node": ">=18" 318 + } 319 + }, 320 + "node_modules/@esbuild/linux-ppc64": { 321 + "version": "0.25.12", 322 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", 323 + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", 324 + "cpu": [ 325 + "ppc64" 326 + ], 327 + "dev": true, 328 + "license": "MIT", 329 + "optional": true, 330 + "os": [ 331 + "linux" 332 + ], 333 + "engines": { 334 + "node": ">=18" 335 + } 336 + }, 337 + "node_modules/@esbuild/linux-riscv64": { 338 + "version": "0.25.12", 339 + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", 340 + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", 341 + "cpu": [ 342 + "riscv64" 343 + ], 344 + "dev": true, 345 + "license": "MIT", 346 + "optional": true, 347 + "os": [ 348 + "linux" 349 + ], 350 + "engines": { 351 + "node": ">=18" 352 + } 353 + }, 354 + "node_modules/@esbuild/linux-s390x": { 355 + "version": "0.25.12", 356 + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", 357 + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", 358 + "cpu": [ 359 + "s390x" 360 + ], 361 + "dev": true, 362 + "license": "MIT", 363 + "optional": true, 364 + "os": [ 365 + "linux" 366 + ], 367 + "engines": { 368 + "node": ">=18" 369 + } 370 + }, 371 + "node_modules/@esbuild/linux-x64": { 372 + "version": "0.25.12", 373 + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", 374 + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", 375 + "cpu": [ 376 + "x64" 377 + ], 378 + "dev": true, 379 + "license": "MIT", 380 + "optional": true, 381 + "os": [ 382 + "linux" 383 + ], 384 + "engines": { 385 + "node": ">=18" 386 + } 387 + }, 388 + "node_modules/@esbuild/netbsd-arm64": { 389 + "version": "0.25.12", 390 + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", 391 + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", 392 + "cpu": [ 393 + "arm64" 394 + ], 395 + "dev": true, 396 + "license": "MIT", 397 + "optional": true, 398 + "os": [ 399 + "netbsd" 400 + ], 401 + "engines": { 402 + "node": ">=18" 403 + } 404 + }, 405 + "node_modules/@esbuild/netbsd-x64": { 406 + "version": "0.25.12", 407 + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", 408 + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", 409 + "cpu": [ 410 + "x64" 411 + ], 412 + "dev": true, 413 + "license": "MIT", 414 + "optional": true, 415 + "os": [ 416 + "netbsd" 417 + ], 418 + "engines": { 419 + "node": ">=18" 420 + } 421 + }, 422 + "node_modules/@esbuild/openbsd-arm64": { 423 + "version": "0.25.12", 424 + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", 425 + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", 426 + "cpu": [ 427 + "arm64" 428 + ], 429 + "dev": true, 430 + "license": "MIT", 431 + "optional": true, 432 + "os": [ 433 + "openbsd" 434 + ], 435 + "engines": { 436 + "node": ">=18" 437 + } 438 + }, 439 + "node_modules/@esbuild/openbsd-x64": { 440 + "version": "0.25.12", 441 + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", 442 + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", 443 + "cpu": [ 444 + "x64" 445 + ], 446 + "dev": true, 447 + "license": "MIT", 448 + "optional": true, 449 + "os": [ 450 + "openbsd" 451 + ], 452 + "engines": { 453 + "node": ">=18" 454 + } 455 + }, 456 + "node_modules/@esbuild/openharmony-arm64": { 457 + "version": "0.25.12", 458 + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", 459 + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", 460 + "cpu": [ 461 + "arm64" 462 + ], 463 + "dev": true, 464 + "license": "MIT", 465 + "optional": true, 466 + "os": [ 467 + "openharmony" 468 + ], 469 + "engines": { 470 + "node": ">=18" 471 + } 472 + }, 473 + "node_modules/@esbuild/sunos-x64": { 474 + "version": "0.25.12", 475 + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", 476 + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", 477 + "cpu": [ 478 + "x64" 479 + ], 480 + "dev": true, 481 + "license": "MIT", 482 + "optional": true, 483 + "os": [ 484 + "sunos" 485 + ], 486 + "engines": { 487 + "node": ">=18" 488 + } 489 + }, 490 + "node_modules/@esbuild/win32-arm64": { 491 + "version": "0.25.12", 492 + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", 493 + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", 494 + "cpu": [ 495 + "arm64" 496 + ], 497 + "dev": true, 498 + "license": "MIT", 499 + "optional": true, 500 + "os": [ 501 + "win32" 502 + ], 503 + "engines": { 504 + "node": ">=18" 505 + } 506 + }, 507 + "node_modules/@esbuild/win32-ia32": { 508 + "version": "0.25.12", 509 + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", 510 + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", 511 + "cpu": [ 512 + "ia32" 513 + ], 514 + "dev": true, 515 + "license": "MIT", 516 + "optional": true, 517 + "os": [ 518 + "win32" 519 + ], 520 + "engines": { 521 + "node": ">=18" 522 + } 523 + }, 524 + "node_modules/@esbuild/win32-x64": { 525 + "version": "0.25.12", 526 + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", 527 + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", 528 + "cpu": [ 529 + "x64" 530 + ], 531 + "dev": true, 532 + "license": "MIT", 533 + "optional": true, 534 + "os": [ 535 + "win32" 536 + ], 537 + "engines": { 538 + "node": ">=18" 539 + } 540 + }, 541 + "node_modules/@isaacs/cliui": { 542 + "version": "8.0.2", 543 + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", 544 + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", 545 + "dev": true, 546 + "license": "ISC", 547 + "dependencies": { 548 + "string-width": "^5.1.2", 549 + "string-width-cjs": "npm:string-width@^4.2.0", 550 + "strip-ansi": "^7.0.1", 551 + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", 552 + "wrap-ansi": "^8.1.0", 553 + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" 554 + }, 555 + "engines": { 556 + "node": ">=12" 557 + } 558 + }, 559 + "node_modules/@istanbuljs/schema": { 560 + "version": "0.1.3", 561 + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", 562 + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", 563 + "dev": true, 564 + "license": "MIT", 565 + "engines": { 566 + "node": ">=8" 567 + } 568 + }, 569 + "node_modules/@jridgewell/gen-mapping": { 570 + "version": "0.3.13", 571 + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", 572 + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", 573 + "dev": true, 574 + "license": "MIT", 575 + "dependencies": { 576 + "@jridgewell/sourcemap-codec": "^1.5.0", 577 + "@jridgewell/trace-mapping": "^0.3.24" 578 + } 579 + }, 580 + "node_modules/@jridgewell/resolve-uri": { 581 + "version": "3.1.2", 582 + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 583 + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 584 + "dev": true, 585 + "license": "MIT", 586 + "engines": { 587 + "node": ">=6.0.0" 588 + } 589 + }, 590 + "node_modules/@jridgewell/sourcemap-codec": { 591 + "version": "1.5.5", 592 + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", 593 + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", 594 + "dev": true, 595 + "license": "MIT" 596 + }, 597 + "node_modules/@jridgewell/trace-mapping": { 598 + "version": "0.3.31", 599 + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", 600 + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", 601 + "dev": true, 602 + "license": "MIT", 603 + "dependencies": { 604 + "@jridgewell/resolve-uri": "^3.1.0", 605 + "@jridgewell/sourcemap-codec": "^1.4.14" 18 606 } 19 607 }, 608 + "node_modules/@pkgjs/parseargs": { 609 + "version": "0.11.0", 610 + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", 611 + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", 612 + "dev": true, 613 + "license": "MIT", 614 + "optional": true, 615 + "engines": { 616 + "node": ">=14" 617 + } 618 + }, 619 + "node_modules/@rollup/rollup-android-arm-eabi": { 620 + "version": "4.53.3", 621 + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", 622 + "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", 623 + "cpu": [ 624 + "arm" 625 + ], 626 + "dev": true, 627 + "license": "MIT", 628 + "optional": true, 629 + "os": [ 630 + "android" 631 + ] 632 + }, 633 + "node_modules/@rollup/rollup-android-arm64": { 634 + "version": "4.53.3", 635 + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", 636 + "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", 637 + "cpu": [ 638 + "arm64" 639 + ], 640 + "dev": true, 641 + "license": "MIT", 642 + "optional": true, 643 + "os": [ 644 + "android" 645 + ] 646 + }, 647 + "node_modules/@rollup/rollup-darwin-arm64": { 648 + "version": "4.53.3", 649 + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", 650 + "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", 651 + "cpu": [ 652 + "arm64" 653 + ], 654 + "dev": true, 655 + "license": "MIT", 656 + "optional": true, 657 + "os": [ 658 + "darwin" 659 + ] 660 + }, 661 + "node_modules/@rollup/rollup-darwin-x64": { 662 + "version": "4.53.3", 663 + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", 664 + "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", 665 + "cpu": [ 666 + "x64" 667 + ], 668 + "dev": true, 669 + "license": "MIT", 670 + "optional": true, 671 + "os": [ 672 + "darwin" 673 + ] 674 + }, 675 + "node_modules/@rollup/rollup-freebsd-arm64": { 676 + "version": "4.53.3", 677 + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", 678 + "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", 679 + "cpu": [ 680 + "arm64" 681 + ], 682 + "dev": true, 683 + "license": "MIT", 684 + "optional": true, 685 + "os": [ 686 + "freebsd" 687 + ] 688 + }, 689 + "node_modules/@rollup/rollup-freebsd-x64": { 690 + "version": "4.53.3", 691 + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", 692 + "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", 693 + "cpu": [ 694 + "x64" 695 + ], 696 + "dev": true, 697 + "license": "MIT", 698 + "optional": true, 699 + "os": [ 700 + "freebsd" 701 + ] 702 + }, 703 + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 704 + "version": "4.53.3", 705 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", 706 + "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", 707 + "cpu": [ 708 + "arm" 709 + ], 710 + "dev": true, 711 + "license": "MIT", 712 + "optional": true, 713 + "os": [ 714 + "linux" 715 + ] 716 + }, 717 + "node_modules/@rollup/rollup-linux-arm-musleabihf": { 718 + "version": "4.53.3", 719 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", 720 + "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", 721 + "cpu": [ 722 + "arm" 723 + ], 724 + "dev": true, 725 + "license": "MIT", 726 + "optional": true, 727 + "os": [ 728 + "linux" 729 + ] 730 + }, 731 + "node_modules/@rollup/rollup-linux-arm64-gnu": { 732 + "version": "4.53.3", 733 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", 734 + "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", 735 + "cpu": [ 736 + "arm64" 737 + ], 738 + "dev": true, 739 + "license": "MIT", 740 + "optional": true, 741 + "os": [ 742 + "linux" 743 + ] 744 + }, 745 + "node_modules/@rollup/rollup-linux-arm64-musl": { 746 + "version": "4.53.3", 747 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", 748 + "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", 749 + "cpu": [ 750 + "arm64" 751 + ], 752 + "dev": true, 753 + "license": "MIT", 754 + "optional": true, 755 + "os": [ 756 + "linux" 757 + ] 758 + }, 759 + "node_modules/@rollup/rollup-linux-loong64-gnu": { 760 + "version": "4.53.3", 761 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", 762 + "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", 763 + "cpu": [ 764 + "loong64" 765 + ], 766 + "dev": true, 767 + "license": "MIT", 768 + "optional": true, 769 + "os": [ 770 + "linux" 771 + ] 772 + }, 773 + "node_modules/@rollup/rollup-linux-ppc64-gnu": { 774 + "version": "4.53.3", 775 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", 776 + "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", 777 + "cpu": [ 778 + "ppc64" 779 + ], 780 + "dev": true, 781 + "license": "MIT", 782 + "optional": true, 783 + "os": [ 784 + "linux" 785 + ] 786 + }, 787 + "node_modules/@rollup/rollup-linux-riscv64-gnu": { 788 + "version": "4.53.3", 789 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", 790 + "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", 791 + "cpu": [ 792 + "riscv64" 793 + ], 794 + "dev": true, 795 + "license": "MIT", 796 + "optional": true, 797 + "os": [ 798 + "linux" 799 + ] 800 + }, 801 + "node_modules/@rollup/rollup-linux-riscv64-musl": { 802 + "version": "4.53.3", 803 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", 804 + "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", 805 + "cpu": [ 806 + "riscv64" 807 + ], 808 + "dev": true, 809 + "license": "MIT", 810 + "optional": true, 811 + "os": [ 812 + "linux" 813 + ] 814 + }, 815 + "node_modules/@rollup/rollup-linux-s390x-gnu": { 816 + "version": "4.53.3", 817 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", 818 + "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", 819 + "cpu": [ 820 + "s390x" 821 + ], 822 + "dev": true, 823 + "license": "MIT", 824 + "optional": true, 825 + "os": [ 826 + "linux" 827 + ] 828 + }, 829 + "node_modules/@rollup/rollup-linux-x64-gnu": { 830 + "version": "4.53.3", 831 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", 832 + "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", 833 + "cpu": [ 834 + "x64" 835 + ], 836 + "dev": true, 837 + "license": "MIT", 838 + "optional": true, 839 + "os": [ 840 + "linux" 841 + ] 842 + }, 843 + "node_modules/@rollup/rollup-linux-x64-musl": { 844 + "version": "4.53.3", 845 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", 846 + "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", 847 + "cpu": [ 848 + "x64" 849 + ], 850 + "dev": true, 851 + "license": "MIT", 852 + "optional": true, 853 + "os": [ 854 + "linux" 855 + ] 856 + }, 857 + "node_modules/@rollup/rollup-openharmony-arm64": { 858 + "version": "4.53.3", 859 + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", 860 + "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", 861 + "cpu": [ 862 + "arm64" 863 + ], 864 + "dev": true, 865 + "license": "MIT", 866 + "optional": true, 867 + "os": [ 868 + "openharmony" 869 + ] 870 + }, 871 + "node_modules/@rollup/rollup-win32-arm64-msvc": { 872 + "version": "4.53.3", 873 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", 874 + "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", 875 + "cpu": [ 876 + "arm64" 877 + ], 878 + "dev": true, 879 + "license": "MIT", 880 + "optional": true, 881 + "os": [ 882 + "win32" 883 + ] 884 + }, 885 + "node_modules/@rollup/rollup-win32-ia32-msvc": { 886 + "version": "4.53.3", 887 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", 888 + "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", 889 + "cpu": [ 890 + "ia32" 891 + ], 892 + "dev": true, 893 + "license": "MIT", 894 + "optional": true, 895 + "os": [ 896 + "win32" 897 + ] 898 + }, 899 + "node_modules/@rollup/rollup-win32-x64-gnu": { 900 + "version": "4.53.3", 901 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", 902 + "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", 903 + "cpu": [ 904 + "x64" 905 + ], 906 + "dev": true, 907 + "license": "MIT", 908 + "optional": true, 909 + "os": [ 910 + "win32" 911 + ] 912 + }, 913 + "node_modules/@rollup/rollup-win32-x64-msvc": { 914 + "version": "4.53.3", 915 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", 916 + "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", 917 + "cpu": [ 918 + "x64" 919 + ], 920 + "dev": true, 921 + "license": "MIT", 922 + "optional": true, 923 + "os": [ 924 + "win32" 925 + ] 926 + }, 927 + "node_modules/@types/chai": { 928 + "version": "5.2.3", 929 + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", 930 + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", 931 + "dev": true, 932 + "license": "MIT", 933 + "dependencies": { 934 + "@types/deep-eql": "*", 935 + "assertion-error": "^2.0.1" 936 + } 937 + }, 938 + "node_modules/@types/deep-eql": { 939 + "version": "4.0.2", 940 + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", 941 + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", 942 + "dev": true, 943 + "license": "MIT" 944 + }, 945 + "node_modules/@types/estree": { 946 + "version": "1.0.8", 947 + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", 948 + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", 949 + "dev": true, 950 + "license": "MIT" 951 + }, 20 952 "node_modules/@types/node": { 21 - "version": "24.3.0", 22 - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz", 23 - "integrity": "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==", 953 + "version": "24.10.1", 954 + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", 955 + "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", 956 + "dev": true, 957 + "license": "MIT", 958 + "dependencies": { 959 + "undici-types": "~7.16.0" 960 + } 961 + }, 962 + "node_modules/@vitest/coverage-v8": { 963 + "version": "3.2.4", 964 + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.2.4.tgz", 965 + "integrity": "sha512-EyF9SXU6kS5Ku/U82E259WSnvg6c8KTjppUncuNdm5QHpe17mwREHnjDzozC8x9MZ0xfBUFSaLkRv4TMA75ALQ==", 966 + "dev": true, 967 + "license": "MIT", 968 + "dependencies": { 969 + "@ampproject/remapping": "^2.3.0", 970 + "@bcoe/v8-coverage": "^1.0.2", 971 + "ast-v8-to-istanbul": "^0.3.3", 972 + "debug": "^4.4.1", 973 + "istanbul-lib-coverage": "^3.2.2", 974 + "istanbul-lib-report": "^3.0.1", 975 + "istanbul-lib-source-maps": "^5.0.6", 976 + "istanbul-reports": "^3.1.7", 977 + "magic-string": "^0.30.17", 978 + "magicast": "^0.3.5", 979 + "std-env": "^3.9.0", 980 + "test-exclude": "^7.0.1", 981 + "tinyrainbow": "^2.0.0" 982 + }, 983 + "funding": { 984 + "url": "https://opencollective.com/vitest" 985 + }, 986 + "peerDependencies": { 987 + "@vitest/browser": "3.2.4", 988 + "vitest": "3.2.4" 989 + }, 990 + "peerDependenciesMeta": { 991 + "@vitest/browser": { 992 + "optional": true 993 + } 994 + } 995 + }, 996 + "node_modules/@vitest/expect": { 997 + "version": "3.2.4", 998 + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", 999 + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", 1000 + "dev": true, 1001 + "license": "MIT", 1002 + "dependencies": { 1003 + "@types/chai": "^5.2.2", 1004 + "@vitest/spy": "3.2.4", 1005 + "@vitest/utils": "3.2.4", 1006 + "chai": "^5.2.0", 1007 + "tinyrainbow": "^2.0.0" 1008 + }, 1009 + "funding": { 1010 + "url": "https://opencollective.com/vitest" 1011 + } 1012 + }, 1013 + "node_modules/@vitest/mocker": { 1014 + "version": "3.2.4", 1015 + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", 1016 + "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", 1017 + "dev": true, 1018 + "license": "MIT", 1019 + "dependencies": { 1020 + "@vitest/spy": "3.2.4", 1021 + "estree-walker": "^3.0.3", 1022 + "magic-string": "^0.30.17" 1023 + }, 1024 + "funding": { 1025 + "url": "https://opencollective.com/vitest" 1026 + }, 1027 + "peerDependencies": { 1028 + "msw": "^2.4.9", 1029 + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" 1030 + }, 1031 + "peerDependenciesMeta": { 1032 + "msw": { 1033 + "optional": true 1034 + }, 1035 + "vite": { 1036 + "optional": true 1037 + } 1038 + } 1039 + }, 1040 + "node_modules/@vitest/pretty-format": { 1041 + "version": "3.2.4", 1042 + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", 1043 + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", 1044 + "dev": true, 1045 + "license": "MIT", 1046 + "dependencies": { 1047 + "tinyrainbow": "^2.0.0" 1048 + }, 1049 + "funding": { 1050 + "url": "https://opencollective.com/vitest" 1051 + } 1052 + }, 1053 + "node_modules/@vitest/runner": { 1054 + "version": "3.2.4", 1055 + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", 1056 + "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", 1057 + "dev": true, 1058 + "license": "MIT", 1059 + "dependencies": { 1060 + "@vitest/utils": "3.2.4", 1061 + "pathe": "^2.0.3", 1062 + "strip-literal": "^3.0.0" 1063 + }, 1064 + "funding": { 1065 + "url": "https://opencollective.com/vitest" 1066 + } 1067 + }, 1068 + "node_modules/@vitest/snapshot": { 1069 + "version": "3.2.4", 1070 + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", 1071 + "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", 1072 + "dev": true, 1073 + "license": "MIT", 1074 + "dependencies": { 1075 + "@vitest/pretty-format": "3.2.4", 1076 + "magic-string": "^0.30.17", 1077 + "pathe": "^2.0.3" 1078 + }, 1079 + "funding": { 1080 + "url": "https://opencollective.com/vitest" 1081 + } 1082 + }, 1083 + "node_modules/@vitest/spy": { 1084 + "version": "3.2.4", 1085 + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", 1086 + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", 1087 + "dev": true, 1088 + "license": "MIT", 1089 + "dependencies": { 1090 + "tinyspy": "^4.0.3" 1091 + }, 1092 + "funding": { 1093 + "url": "https://opencollective.com/vitest" 1094 + } 1095 + }, 1096 + "node_modules/@vitest/utils": { 1097 + "version": "3.2.4", 1098 + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", 1099 + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", 1100 + "dev": true, 1101 + "license": "MIT", 1102 + "dependencies": { 1103 + "@vitest/pretty-format": "3.2.4", 1104 + "loupe": "^3.1.4", 1105 + "tinyrainbow": "^2.0.0" 1106 + }, 1107 + "funding": { 1108 + "url": "https://opencollective.com/vitest" 1109 + } 1110 + }, 1111 + "node_modules/ansi-regex": { 1112 + "version": "6.2.2", 1113 + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", 1114 + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", 1115 + "dev": true, 1116 + "license": "MIT", 1117 + "engines": { 1118 + "node": ">=12" 1119 + }, 1120 + "funding": { 1121 + "url": "https://github.com/chalk/ansi-regex?sponsor=1" 1122 + } 1123 + }, 1124 + "node_modules/ansi-styles": { 1125 + "version": "6.2.3", 1126 + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", 1127 + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", 1128 + "dev": true, 1129 + "license": "MIT", 1130 + "engines": { 1131 + "node": ">=12" 1132 + }, 1133 + "funding": { 1134 + "url": "https://github.com/chalk/ansi-styles?sponsor=1" 1135 + } 1136 + }, 1137 + "node_modules/assertion-error": { 1138 + "version": "2.0.1", 1139 + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", 1140 + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", 1141 + "dev": true, 1142 + "license": "MIT", 1143 + "engines": { 1144 + "node": ">=12" 1145 + } 1146 + }, 1147 + "node_modules/ast-v8-to-istanbul": { 1148 + "version": "0.3.8", 1149 + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.8.tgz", 1150 + "integrity": "sha512-szgSZqUxI5T8mLKvS7WTjF9is+MVbOeLADU73IseOcrqhxr/VAvy6wfoVE39KnKzA7JRhjF5eUagNlHwvZPlKQ==", 24 1151 "dev": true, 25 1152 "license": "MIT", 26 1153 "dependencies": { 27 - "undici-types": "~7.10.0" 1154 + "@jridgewell/trace-mapping": "^0.3.31", 1155 + "estree-walker": "^3.0.3", 1156 + "js-tokens": "^9.0.1" 28 1157 } 29 1158 }, 1159 + "node_modules/balanced-match": { 1160 + "version": "1.0.2", 1161 + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 1162 + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 1163 + "dev": true, 1164 + "license": "MIT" 1165 + }, 1166 + "node_modules/brace-expansion": { 1167 + "version": "2.0.2", 1168 + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", 1169 + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", 1170 + "dev": true, 1171 + "license": "MIT", 1172 + "dependencies": { 1173 + "balanced-match": "^1.0.0" 1174 + } 1175 + }, 1176 + "node_modules/cac": { 1177 + "version": "6.7.14", 1178 + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", 1179 + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", 1180 + "dev": true, 1181 + "license": "MIT", 1182 + "engines": { 1183 + "node": ">=8" 1184 + } 1185 + }, 1186 + "node_modules/chai": { 1187 + "version": "5.3.3", 1188 + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", 1189 + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", 1190 + "dev": true, 1191 + "license": "MIT", 1192 + "dependencies": { 1193 + "assertion-error": "^2.0.1", 1194 + "check-error": "^2.1.1", 1195 + "deep-eql": "^5.0.1", 1196 + "loupe": "^3.1.0", 1197 + "pathval": "^2.0.0" 1198 + }, 1199 + "engines": { 1200 + "node": ">=18" 1201 + } 1202 + }, 1203 + "node_modules/check-error": { 1204 + "version": "2.1.1", 1205 + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", 1206 + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", 1207 + "dev": true, 1208 + "license": "MIT", 1209 + "engines": { 1210 + "node": ">= 16" 1211 + } 1212 + }, 1213 + "node_modules/color-convert": { 1214 + "version": "2.0.1", 1215 + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1216 + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1217 + "dev": true, 1218 + "license": "MIT", 1219 + "dependencies": { 1220 + "color-name": "~1.1.4" 1221 + }, 1222 + "engines": { 1223 + "node": ">=7.0.0" 1224 + } 1225 + }, 1226 + "node_modules/color-name": { 1227 + "version": "1.1.4", 1228 + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1229 + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 1230 + "dev": true, 1231 + "license": "MIT" 1232 + }, 1233 + "node_modules/cross-spawn": { 1234 + "version": "7.0.6", 1235 + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", 1236 + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", 1237 + "dev": true, 1238 + "license": "MIT", 1239 + "dependencies": { 1240 + "path-key": "^3.1.0", 1241 + "shebang-command": "^2.0.0", 1242 + "which": "^2.0.1" 1243 + }, 1244 + "engines": { 1245 + "node": ">= 8" 1246 + } 1247 + }, 1248 + "node_modules/debug": { 1249 + "version": "4.4.1", 1250 + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", 1251 + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", 1252 + "dev": true, 1253 + "license": "MIT", 1254 + "dependencies": { 1255 + "ms": "^2.1.3" 1256 + }, 1257 + "engines": { 1258 + "node": ">=6.0" 1259 + }, 1260 + "peerDependenciesMeta": { 1261 + "supports-color": { 1262 + "optional": true 1263 + } 1264 + } 1265 + }, 1266 + "node_modules/deep-eql": { 1267 + "version": "5.0.2", 1268 + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", 1269 + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", 1270 + "dev": true, 1271 + "license": "MIT", 1272 + "engines": { 1273 + "node": ">=6" 1274 + } 1275 + }, 1276 + "node_modules/eastasianwidth": { 1277 + "version": "0.2.0", 1278 + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", 1279 + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", 1280 + "dev": true, 1281 + "license": "MIT" 1282 + }, 1283 + "node_modules/emoji-regex": { 1284 + "version": "9.2.2", 1285 + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", 1286 + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", 1287 + "dev": true, 1288 + "license": "MIT" 1289 + }, 1290 + "node_modules/es-module-lexer": { 1291 + "version": "1.7.0", 1292 + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", 1293 + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", 1294 + "dev": true, 1295 + "license": "MIT" 1296 + }, 1297 + "node_modules/esbuild": { 1298 + "version": "0.25.12", 1299 + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", 1300 + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", 1301 + "dev": true, 1302 + "hasInstallScript": true, 1303 + "license": "MIT", 1304 + "bin": { 1305 + "esbuild": "bin/esbuild" 1306 + }, 1307 + "engines": { 1308 + "node": ">=18" 1309 + }, 1310 + "optionalDependencies": { 1311 + "@esbuild/aix-ppc64": "0.25.12", 1312 + "@esbuild/android-arm": "0.25.12", 1313 + "@esbuild/android-arm64": "0.25.12", 1314 + "@esbuild/android-x64": "0.25.12", 1315 + "@esbuild/darwin-arm64": "0.25.12", 1316 + "@esbuild/darwin-x64": "0.25.12", 1317 + "@esbuild/freebsd-arm64": "0.25.12", 1318 + "@esbuild/freebsd-x64": "0.25.12", 1319 + "@esbuild/linux-arm": "0.25.12", 1320 + "@esbuild/linux-arm64": "0.25.12", 1321 + "@esbuild/linux-ia32": "0.25.12", 1322 + "@esbuild/linux-loong64": "0.25.12", 1323 + "@esbuild/linux-mips64el": "0.25.12", 1324 + "@esbuild/linux-ppc64": "0.25.12", 1325 + "@esbuild/linux-riscv64": "0.25.12", 1326 + "@esbuild/linux-s390x": "0.25.12", 1327 + "@esbuild/linux-x64": "0.25.12", 1328 + "@esbuild/netbsd-arm64": "0.25.12", 1329 + "@esbuild/netbsd-x64": "0.25.12", 1330 + "@esbuild/openbsd-arm64": "0.25.12", 1331 + "@esbuild/openbsd-x64": "0.25.12", 1332 + "@esbuild/openharmony-arm64": "0.25.12", 1333 + "@esbuild/sunos-x64": "0.25.12", 1334 + "@esbuild/win32-arm64": "0.25.12", 1335 + "@esbuild/win32-ia32": "0.25.12", 1336 + "@esbuild/win32-x64": "0.25.12" 1337 + } 1338 + }, 1339 + "node_modules/estree-walker": { 1340 + "version": "3.0.3", 1341 + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", 1342 + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", 1343 + "dev": true, 1344 + "license": "MIT", 1345 + "dependencies": { 1346 + "@types/estree": "^1.0.0" 1347 + } 1348 + }, 1349 + "node_modules/expect-type": { 1350 + "version": "1.2.2", 1351 + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", 1352 + "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", 1353 + "dev": true, 1354 + "license": "Apache-2.0", 1355 + "engines": { 1356 + "node": ">=12.0.0" 1357 + } 1358 + }, 1359 + "node_modules/fdir": { 1360 + "version": "6.5.0", 1361 + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", 1362 + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", 1363 + "dev": true, 1364 + "license": "MIT", 1365 + "engines": { 1366 + "node": ">=12.0.0" 1367 + }, 1368 + "peerDependencies": { 1369 + "picomatch": "^3 || ^4" 1370 + }, 1371 + "peerDependenciesMeta": { 1372 + "picomatch": { 1373 + "optional": true 1374 + } 1375 + } 1376 + }, 1377 + "node_modules/foreground-child": { 1378 + "version": "3.3.1", 1379 + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", 1380 + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", 1381 + "dev": true, 1382 + "license": "ISC", 1383 + "dependencies": { 1384 + "cross-spawn": "^7.0.6", 1385 + "signal-exit": "^4.0.1" 1386 + }, 1387 + "engines": { 1388 + "node": ">=14" 1389 + }, 1390 + "funding": { 1391 + "url": "https://github.com/sponsors/isaacs" 1392 + } 1393 + }, 1394 + "node_modules/fsevents": { 1395 + "version": "2.3.3", 1396 + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1397 + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1398 + "dev": true, 1399 + "hasInstallScript": true, 1400 + "license": "MIT", 1401 + "optional": true, 1402 + "os": [ 1403 + "darwin" 1404 + ], 1405 + "engines": { 1406 + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1407 + } 1408 + }, 1409 + "node_modules/glob": { 1410 + "version": "10.5.0", 1411 + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", 1412 + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", 1413 + "dev": true, 1414 + "license": "ISC", 1415 + "dependencies": { 1416 + "foreground-child": "^3.1.0", 1417 + "jackspeak": "^3.1.2", 1418 + "minimatch": "^9.0.4", 1419 + "minipass": "^7.1.2", 1420 + "package-json-from-dist": "^1.0.0", 1421 + "path-scurry": "^1.11.1" 1422 + }, 1423 + "bin": { 1424 + "glob": "dist/esm/bin.mjs" 1425 + }, 1426 + "funding": { 1427 + "url": "https://github.com/sponsors/isaacs" 1428 + } 1429 + }, 1430 + "node_modules/has-flag": { 1431 + "version": "4.0.0", 1432 + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1433 + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1434 + "dev": true, 1435 + "license": "MIT", 1436 + "engines": { 1437 + "node": ">=8" 1438 + } 1439 + }, 1440 + "node_modules/html-escaper": { 1441 + "version": "2.0.2", 1442 + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", 1443 + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", 1444 + "dev": true, 1445 + "license": "MIT" 1446 + }, 1447 + "node_modules/is-fullwidth-code-point": { 1448 + "version": "3.0.0", 1449 + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 1450 + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 1451 + "dev": true, 1452 + "license": "MIT", 1453 + "engines": { 1454 + "node": ">=8" 1455 + } 1456 + }, 1457 + "node_modules/isexe": { 1458 + "version": "2.0.0", 1459 + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1460 + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 1461 + "dev": true, 1462 + "license": "ISC" 1463 + }, 1464 + "node_modules/istanbul-lib-coverage": { 1465 + "version": "3.2.2", 1466 + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", 1467 + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", 1468 + "dev": true, 1469 + "license": "BSD-3-Clause", 1470 + "engines": { 1471 + "node": ">=8" 1472 + } 1473 + }, 1474 + "node_modules/istanbul-lib-report": { 1475 + "version": "3.0.1", 1476 + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", 1477 + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", 1478 + "dev": true, 1479 + "license": "BSD-3-Clause", 1480 + "dependencies": { 1481 + "istanbul-lib-coverage": "^3.0.0", 1482 + "make-dir": "^4.0.0", 1483 + "supports-color": "^7.1.0" 1484 + }, 1485 + "engines": { 1486 + "node": ">=10" 1487 + } 1488 + }, 1489 + "node_modules/istanbul-lib-source-maps": { 1490 + "version": "5.0.6", 1491 + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", 1492 + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", 1493 + "dev": true, 1494 + "license": "BSD-3-Clause", 1495 + "dependencies": { 1496 + "@jridgewell/trace-mapping": "^0.3.23", 1497 + "debug": "^4.1.1", 1498 + "istanbul-lib-coverage": "^3.0.0" 1499 + }, 1500 + "engines": { 1501 + "node": ">=10" 1502 + } 1503 + }, 1504 + "node_modules/istanbul-reports": { 1505 + "version": "3.2.0", 1506 + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", 1507 + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", 1508 + "dev": true, 1509 + "license": "BSD-3-Clause", 1510 + "dependencies": { 1511 + "html-escaper": "^2.0.0", 1512 + "istanbul-lib-report": "^3.0.0" 1513 + }, 1514 + "engines": { 1515 + "node": ">=8" 1516 + } 1517 + }, 1518 + "node_modules/jackspeak": { 1519 + "version": "3.4.3", 1520 + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", 1521 + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", 1522 + "dev": true, 1523 + "license": "BlueOak-1.0.0", 1524 + "dependencies": { 1525 + "@isaacs/cliui": "^8.0.2" 1526 + }, 1527 + "funding": { 1528 + "url": "https://github.com/sponsors/isaacs" 1529 + }, 1530 + "optionalDependencies": { 1531 + "@pkgjs/parseargs": "^0.11.0" 1532 + } 1533 + }, 1534 + "node_modules/js-tokens": { 1535 + "version": "9.0.1", 1536 + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", 1537 + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", 1538 + "dev": true, 1539 + "license": "MIT" 1540 + }, 30 1541 "node_modules/json5": { 31 1542 "version": "2.2.3", 32 1543 "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", ··· 39 1550 "node": ">=6" 40 1551 } 41 1552 }, 42 - "node_modules/node-fetch": { 43 - "version": "2.7.0", 44 - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", 45 - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", 1553 + "node_modules/loupe": { 1554 + "version": "3.2.1", 1555 + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", 1556 + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", 1557 + "dev": true, 1558 + "license": "MIT" 1559 + }, 1560 + "node_modules/lru-cache": { 1561 + "version": "10.4.3", 1562 + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", 1563 + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", 1564 + "dev": true, 1565 + "license": "ISC" 1566 + }, 1567 + "node_modules/magic-string": { 1568 + "version": "0.30.21", 1569 + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", 1570 + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", 1571 + "dev": true, 1572 + "license": "MIT", 1573 + "dependencies": { 1574 + "@jridgewell/sourcemap-codec": "^1.5.5" 1575 + } 1576 + }, 1577 + "node_modules/magicast": { 1578 + "version": "0.3.5", 1579 + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", 1580 + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", 1581 + "dev": true, 46 1582 "license": "MIT", 47 1583 "dependencies": { 48 - "whatwg-url": "^5.0.0" 1584 + "@babel/parser": "^7.25.4", 1585 + "@babel/types": "^7.25.4", 1586 + "source-map-js": "^1.2.0" 1587 + } 1588 + }, 1589 + "node_modules/make-dir": { 1590 + "version": "4.0.0", 1591 + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", 1592 + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", 1593 + "dev": true, 1594 + "license": "MIT", 1595 + "dependencies": { 1596 + "semver": "^7.5.3" 49 1597 }, 50 1598 "engines": { 51 - "node": "4.x || >=6.0.0" 1599 + "node": ">=10" 52 1600 }, 53 - "peerDependencies": { 54 - "encoding": "^0.1.0" 1601 + "funding": { 1602 + "url": "https://github.com/sponsors/sindresorhus" 1603 + } 1604 + }, 1605 + "node_modules/minimatch": { 1606 + "version": "9.0.5", 1607 + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", 1608 + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", 1609 + "dev": true, 1610 + "license": "ISC", 1611 + "dependencies": { 1612 + "brace-expansion": "^2.0.1" 55 1613 }, 56 - "peerDependenciesMeta": { 57 - "encoding": { 58 - "optional": true 1614 + "engines": { 1615 + "node": ">=16 || 14 >=14.17" 1616 + }, 1617 + "funding": { 1618 + "url": "https://github.com/sponsors/isaacs" 1619 + } 1620 + }, 1621 + "node_modules/minipass": { 1622 + "version": "7.1.2", 1623 + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", 1624 + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", 1625 + "dev": true, 1626 + "license": "ISC", 1627 + "engines": { 1628 + "node": ">=16 || 14 >=14.17" 1629 + } 1630 + }, 1631 + "node_modules/ms": { 1632 + "version": "2.1.3", 1633 + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1634 + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1635 + "dev": true, 1636 + "license": "MIT" 1637 + }, 1638 + "node_modules/nanoid": { 1639 + "version": "3.3.11", 1640 + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", 1641 + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", 1642 + "dev": true, 1643 + "funding": [ 1644 + { 1645 + "type": "github", 1646 + "url": "https://github.com/sponsors/ai" 59 1647 } 1648 + ], 1649 + "license": "MIT", 1650 + "bin": { 1651 + "nanoid": "bin/nanoid.cjs" 1652 + }, 1653 + "engines": { 1654 + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 60 1655 } 61 1656 }, 62 - "node_modules/openweathermap-ts": { 63 - "version": "1.2.10", 64 - "resolved": "https://registry.npmjs.org/openweathermap-ts/-/openweathermap-ts-1.2.10.tgz", 65 - "integrity": "sha512-Zckv2aXN8ENSeAeroces2jJciLWb6aLNXEmvG6pmF+BcIMw2kwRo6++/AKUNoU5suOp47UWA6lllDV0TNm//OA==", 1657 + "node_modules/openweather-api-node": { 1658 + "version": "3.1.5", 1659 + "resolved": "https://registry.npmjs.org/openweather-api-node/-/openweather-api-node-3.1.5.tgz", 1660 + "integrity": "sha512-FGLE0bWOTvp4XHaswmzMfisYMMEtwEwOEJR0vaS07L31OUcutV/UUO5/vRuktkRPoqfk3KZOoqddsRTGTxT7Aw==", 1661 + "license": "MIT" 1662 + }, 1663 + "node_modules/package-json-from-dist": { 1664 + "version": "1.0.1", 1665 + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", 1666 + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", 1667 + "dev": true, 1668 + "license": "BlueOak-1.0.0" 1669 + }, 1670 + "node_modules/path-key": { 1671 + "version": "3.1.1", 1672 + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 1673 + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1674 + "dev": true, 66 1675 "license": "MIT", 1676 + "engines": { 1677 + "node": ">=8" 1678 + } 1679 + }, 1680 + "node_modules/path-scurry": { 1681 + "version": "1.11.1", 1682 + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", 1683 + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", 1684 + "dev": true, 1685 + "license": "BlueOak-1.0.0", 67 1686 "dependencies": { 68 - "node-fetch": "^2.6.0" 1687 + "lru-cache": "^10.2.0", 1688 + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" 1689 + }, 1690 + "engines": { 1691 + "node": ">=16 || 14 >=14.18" 1692 + }, 1693 + "funding": { 1694 + "url": "https://github.com/sponsors/isaacs" 69 1695 } 70 1696 }, 71 - "node_modules/tr46": { 72 - "version": "0.0.3", 73 - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 74 - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", 1697 + "node_modules/pathe": { 1698 + "version": "2.0.3", 1699 + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", 1700 + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", 1701 + "dev": true, 75 1702 "license": "MIT" 76 1703 }, 1704 + "node_modules/pathval": { 1705 + "version": "2.0.1", 1706 + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", 1707 + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", 1708 + "dev": true, 1709 + "license": "MIT", 1710 + "engines": { 1711 + "node": ">= 14.16" 1712 + } 1713 + }, 1714 + "node_modules/picocolors": { 1715 + "version": "1.1.1", 1716 + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", 1717 + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", 1718 + "dev": true, 1719 + "license": "ISC" 1720 + }, 1721 + "node_modules/picomatch": { 1722 + "version": "4.0.3", 1723 + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", 1724 + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", 1725 + "dev": true, 1726 + "license": "MIT", 1727 + "engines": { 1728 + "node": ">=12" 1729 + }, 1730 + "funding": { 1731 + "url": "https://github.com/sponsors/jonschlinkert" 1732 + } 1733 + }, 1734 + "node_modules/postcss": { 1735 + "version": "8.5.6", 1736 + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", 1737 + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", 1738 + "dev": true, 1739 + "funding": [ 1740 + { 1741 + "type": "opencollective", 1742 + "url": "https://opencollective.com/postcss/" 1743 + }, 1744 + { 1745 + "type": "tidelift", 1746 + "url": "https://tidelift.com/funding/github/npm/postcss" 1747 + }, 1748 + { 1749 + "type": "github", 1750 + "url": "https://github.com/sponsors/ai" 1751 + } 1752 + ], 1753 + "license": "MIT", 1754 + "dependencies": { 1755 + "nanoid": "^3.3.11", 1756 + "picocolors": "^1.1.1", 1757 + "source-map-js": "^1.2.1" 1758 + }, 1759 + "engines": { 1760 + "node": "^10 || ^12 || >=14" 1761 + } 1762 + }, 1763 + "node_modules/rollup": { 1764 + "version": "4.53.3", 1765 + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", 1766 + "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", 1767 + "dev": true, 1768 + "license": "MIT", 1769 + "dependencies": { 1770 + "@types/estree": "1.0.8" 1771 + }, 1772 + "bin": { 1773 + "rollup": "dist/bin/rollup" 1774 + }, 1775 + "engines": { 1776 + "node": ">=18.0.0", 1777 + "npm": ">=8.0.0" 1778 + }, 1779 + "optionalDependencies": { 1780 + "@rollup/rollup-android-arm-eabi": "4.53.3", 1781 + "@rollup/rollup-android-arm64": "4.53.3", 1782 + "@rollup/rollup-darwin-arm64": "4.53.3", 1783 + "@rollup/rollup-darwin-x64": "4.53.3", 1784 + "@rollup/rollup-freebsd-arm64": "4.53.3", 1785 + "@rollup/rollup-freebsd-x64": "4.53.3", 1786 + "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", 1787 + "@rollup/rollup-linux-arm-musleabihf": "4.53.3", 1788 + "@rollup/rollup-linux-arm64-gnu": "4.53.3", 1789 + "@rollup/rollup-linux-arm64-musl": "4.53.3", 1790 + "@rollup/rollup-linux-loong64-gnu": "4.53.3", 1791 + "@rollup/rollup-linux-ppc64-gnu": "4.53.3", 1792 + "@rollup/rollup-linux-riscv64-gnu": "4.53.3", 1793 + "@rollup/rollup-linux-riscv64-musl": "4.53.3", 1794 + "@rollup/rollup-linux-s390x-gnu": "4.53.3", 1795 + "@rollup/rollup-linux-x64-gnu": "4.53.3", 1796 + "@rollup/rollup-linux-x64-musl": "4.53.3", 1797 + "@rollup/rollup-openharmony-arm64": "4.53.3", 1798 + "@rollup/rollup-win32-arm64-msvc": "4.53.3", 1799 + "@rollup/rollup-win32-ia32-msvc": "4.53.3", 1800 + "@rollup/rollup-win32-x64-gnu": "4.53.3", 1801 + "@rollup/rollup-win32-x64-msvc": "4.53.3", 1802 + "fsevents": "~2.3.2" 1803 + } 1804 + }, 1805 + "node_modules/semver": { 1806 + "version": "7.7.2", 1807 + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", 1808 + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", 1809 + "dev": true, 1810 + "license": "ISC", 1811 + "bin": { 1812 + "semver": "bin/semver.js" 1813 + }, 1814 + "engines": { 1815 + "node": ">=10" 1816 + } 1817 + }, 1818 + "node_modules/shebang-command": { 1819 + "version": "2.0.0", 1820 + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1821 + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1822 + "dev": true, 1823 + "license": "MIT", 1824 + "dependencies": { 1825 + "shebang-regex": "^3.0.0" 1826 + }, 1827 + "engines": { 1828 + "node": ">=8" 1829 + } 1830 + }, 1831 + "node_modules/shebang-regex": { 1832 + "version": "3.0.0", 1833 + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1834 + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1835 + "dev": true, 1836 + "license": "MIT", 1837 + "engines": { 1838 + "node": ">=8" 1839 + } 1840 + }, 1841 + "node_modules/siginfo": { 1842 + "version": "2.0.0", 1843 + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", 1844 + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", 1845 + "dev": true, 1846 + "license": "ISC" 1847 + }, 1848 + "node_modules/signal-exit": { 1849 + "version": "4.1.0", 1850 + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", 1851 + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", 1852 + "dev": true, 1853 + "license": "ISC", 1854 + "engines": { 1855 + "node": ">=14" 1856 + }, 1857 + "funding": { 1858 + "url": "https://github.com/sponsors/isaacs" 1859 + } 1860 + }, 1861 + "node_modules/source-map-js": { 1862 + "version": "1.2.1", 1863 + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", 1864 + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", 1865 + "dev": true, 1866 + "license": "BSD-3-Clause", 1867 + "engines": { 1868 + "node": ">=0.10.0" 1869 + } 1870 + }, 1871 + "node_modules/stackback": { 1872 + "version": "0.0.2", 1873 + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", 1874 + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", 1875 + "dev": true, 1876 + "license": "MIT" 1877 + }, 1878 + "node_modules/std-env": { 1879 + "version": "3.10.0", 1880 + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", 1881 + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", 1882 + "dev": true, 1883 + "license": "MIT" 1884 + }, 1885 + "node_modules/string-width": { 1886 + "version": "5.1.2", 1887 + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", 1888 + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", 1889 + "dev": true, 1890 + "license": "MIT", 1891 + "dependencies": { 1892 + "eastasianwidth": "^0.2.0", 1893 + "emoji-regex": "^9.2.2", 1894 + "strip-ansi": "^7.0.1" 1895 + }, 1896 + "engines": { 1897 + "node": ">=12" 1898 + }, 1899 + "funding": { 1900 + "url": "https://github.com/sponsors/sindresorhus" 1901 + } 1902 + }, 1903 + "node_modules/string-width-cjs": { 1904 + "name": "string-width", 1905 + "version": "4.2.3", 1906 + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1907 + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1908 + "dev": true, 1909 + "license": "MIT", 1910 + "dependencies": { 1911 + "emoji-regex": "^8.0.0", 1912 + "is-fullwidth-code-point": "^3.0.0", 1913 + "strip-ansi": "^6.0.1" 1914 + }, 1915 + "engines": { 1916 + "node": ">=8" 1917 + } 1918 + }, 1919 + "node_modules/string-width-cjs/node_modules/ansi-regex": { 1920 + "version": "5.0.1", 1921 + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1922 + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 1923 + "dev": true, 1924 + "license": "MIT", 1925 + "engines": { 1926 + "node": ">=8" 1927 + } 1928 + }, 1929 + "node_modules/string-width-cjs/node_modules/emoji-regex": { 1930 + "version": "8.0.0", 1931 + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1932 + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 1933 + "dev": true, 1934 + "license": "MIT" 1935 + }, 1936 + "node_modules/string-width-cjs/node_modules/strip-ansi": { 1937 + "version": "6.0.1", 1938 + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1939 + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1940 + "dev": true, 1941 + "license": "MIT", 1942 + "dependencies": { 1943 + "ansi-regex": "^5.0.1" 1944 + }, 1945 + "engines": { 1946 + "node": ">=8" 1947 + } 1948 + }, 1949 + "node_modules/strip-ansi": { 1950 + "version": "7.1.2", 1951 + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", 1952 + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", 1953 + "dev": true, 1954 + "license": "MIT", 1955 + "dependencies": { 1956 + "ansi-regex": "^6.0.1" 1957 + }, 1958 + "engines": { 1959 + "node": ">=12" 1960 + }, 1961 + "funding": { 1962 + "url": "https://github.com/chalk/strip-ansi?sponsor=1" 1963 + } 1964 + }, 1965 + "node_modules/strip-ansi-cjs": { 1966 + "name": "strip-ansi", 1967 + "version": "6.0.1", 1968 + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1969 + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1970 + "dev": true, 1971 + "license": "MIT", 1972 + "dependencies": { 1973 + "ansi-regex": "^5.0.1" 1974 + }, 1975 + "engines": { 1976 + "node": ">=8" 1977 + } 1978 + }, 1979 + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { 1980 + "version": "5.0.1", 1981 + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1982 + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 1983 + "dev": true, 1984 + "license": "MIT", 1985 + "engines": { 1986 + "node": ">=8" 1987 + } 1988 + }, 1989 + "node_modules/strip-literal": { 1990 + "version": "3.1.0", 1991 + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz", 1992 + "integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==", 1993 + "dev": true, 1994 + "license": "MIT", 1995 + "dependencies": { 1996 + "js-tokens": "^9.0.1" 1997 + }, 1998 + "funding": { 1999 + "url": "https://github.com/sponsors/antfu" 2000 + } 2001 + }, 2002 + "node_modules/supports-color": { 2003 + "version": "7.2.0", 2004 + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 2005 + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 2006 + "dev": true, 2007 + "license": "MIT", 2008 + "dependencies": { 2009 + "has-flag": "^4.0.0" 2010 + }, 2011 + "engines": { 2012 + "node": ">=8" 2013 + } 2014 + }, 2015 + "node_modules/test-exclude": { 2016 + "version": "7.0.1", 2017 + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", 2018 + "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", 2019 + "dev": true, 2020 + "license": "ISC", 2021 + "dependencies": { 2022 + "@istanbuljs/schema": "^0.1.2", 2023 + "glob": "^10.4.1", 2024 + "minimatch": "^9.0.4" 2025 + }, 2026 + "engines": { 2027 + "node": ">=18" 2028 + } 2029 + }, 2030 + "node_modules/tinybench": { 2031 + "version": "2.9.0", 2032 + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", 2033 + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", 2034 + "dev": true, 2035 + "license": "MIT" 2036 + }, 2037 + "node_modules/tinyexec": { 2038 + "version": "0.3.2", 2039 + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", 2040 + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", 2041 + "dev": true, 2042 + "license": "MIT" 2043 + }, 2044 + "node_modules/tinyglobby": { 2045 + "version": "0.2.15", 2046 + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", 2047 + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", 2048 + "dev": true, 2049 + "license": "MIT", 2050 + "dependencies": { 2051 + "fdir": "^6.5.0", 2052 + "picomatch": "^4.0.3" 2053 + }, 2054 + "engines": { 2055 + "node": ">=12.0.0" 2056 + }, 2057 + "funding": { 2058 + "url": "https://github.com/sponsors/SuperchupuDev" 2059 + } 2060 + }, 2061 + "node_modules/tinypool": { 2062 + "version": "1.1.1", 2063 + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", 2064 + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", 2065 + "dev": true, 2066 + "license": "MIT", 2067 + "engines": { 2068 + "node": "^18.0.0 || >=20.0.0" 2069 + } 2070 + }, 2071 + "node_modules/tinyrainbow": { 2072 + "version": "2.0.0", 2073 + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", 2074 + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", 2075 + "dev": true, 2076 + "license": "MIT", 2077 + "engines": { 2078 + "node": ">=14.0.0" 2079 + } 2080 + }, 2081 + "node_modules/tinyspy": { 2082 + "version": "4.0.4", 2083 + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz", 2084 + "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==", 2085 + "dev": true, 2086 + "license": "MIT", 2087 + "engines": { 2088 + "node": ">=14.0.0" 2089 + } 2090 + }, 77 2091 "node_modules/typescript": { 78 - "version": "5.9.2", 79 - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", 80 - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", 2092 + "version": "5.9.3", 2093 + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", 2094 + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", 81 2095 "dev": true, 82 2096 "license": "Apache-2.0", 83 2097 "bin": { ··· 89 2103 } 90 2104 }, 91 2105 "node_modules/undici-types": { 92 - "version": "7.10.0", 93 - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", 94 - "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", 2106 + "version": "7.16.0", 2107 + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", 2108 + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", 95 2109 "dev": true, 96 2110 "license": "MIT" 97 2111 }, 98 - "node_modules/webidl-conversions": { 99 - "version": "3.0.1", 100 - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 101 - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", 102 - "license": "BSD-2-Clause" 2112 + "node_modules/vite": { 2113 + "version": "7.2.6", 2114 + "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.6.tgz", 2115 + "integrity": "sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==", 2116 + "dev": true, 2117 + "license": "MIT", 2118 + "dependencies": { 2119 + "esbuild": "^0.25.0", 2120 + "fdir": "^6.5.0", 2121 + "picomatch": "^4.0.3", 2122 + "postcss": "^8.5.6", 2123 + "rollup": "^4.43.0", 2124 + "tinyglobby": "^0.2.15" 2125 + }, 2126 + "bin": { 2127 + "vite": "bin/vite.js" 2128 + }, 2129 + "engines": { 2130 + "node": "^20.19.0 || >=22.12.0" 2131 + }, 2132 + "funding": { 2133 + "url": "https://github.com/vitejs/vite?sponsor=1" 2134 + }, 2135 + "optionalDependencies": { 2136 + "fsevents": "~2.3.3" 2137 + }, 2138 + "peerDependencies": { 2139 + "@types/node": "^20.19.0 || >=22.12.0", 2140 + "jiti": ">=1.21.0", 2141 + "less": "^4.0.0", 2142 + "lightningcss": "^1.21.0", 2143 + "sass": "^1.70.0", 2144 + "sass-embedded": "^1.70.0", 2145 + "stylus": ">=0.54.8", 2146 + "sugarss": "^5.0.0", 2147 + "terser": "^5.16.0", 2148 + "tsx": "^4.8.1", 2149 + "yaml": "^2.4.2" 2150 + }, 2151 + "peerDependenciesMeta": { 2152 + "@types/node": { 2153 + "optional": true 2154 + }, 2155 + "jiti": { 2156 + "optional": true 2157 + }, 2158 + "less": { 2159 + "optional": true 2160 + }, 2161 + "lightningcss": { 2162 + "optional": true 2163 + }, 2164 + "sass": { 2165 + "optional": true 2166 + }, 2167 + "sass-embedded": { 2168 + "optional": true 2169 + }, 2170 + "stylus": { 2171 + "optional": true 2172 + }, 2173 + "sugarss": { 2174 + "optional": true 2175 + }, 2176 + "terser": { 2177 + "optional": true 2178 + }, 2179 + "tsx": { 2180 + "optional": true 2181 + }, 2182 + "yaml": { 2183 + "optional": true 2184 + } 2185 + } 103 2186 }, 104 - "node_modules/whatwg-url": { 105 - "version": "5.0.0", 106 - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 107 - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", 2187 + "node_modules/vite-node": { 2188 + "version": "3.2.4", 2189 + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", 2190 + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", 2191 + "dev": true, 2192 + "license": "MIT", 2193 + "dependencies": { 2194 + "cac": "^6.7.14", 2195 + "debug": "^4.4.1", 2196 + "es-module-lexer": "^1.7.0", 2197 + "pathe": "^2.0.3", 2198 + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" 2199 + }, 2200 + "bin": { 2201 + "vite-node": "vite-node.mjs" 2202 + }, 2203 + "engines": { 2204 + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 2205 + }, 2206 + "funding": { 2207 + "url": "https://opencollective.com/vitest" 2208 + } 2209 + }, 2210 + "node_modules/vitest": { 2211 + "version": "3.2.4", 2212 + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", 2213 + "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", 2214 + "dev": true, 2215 + "license": "MIT", 2216 + "dependencies": { 2217 + "@types/chai": "^5.2.2", 2218 + "@vitest/expect": "3.2.4", 2219 + "@vitest/mocker": "3.2.4", 2220 + "@vitest/pretty-format": "^3.2.4", 2221 + "@vitest/runner": "3.2.4", 2222 + "@vitest/snapshot": "3.2.4", 2223 + "@vitest/spy": "3.2.4", 2224 + "@vitest/utils": "3.2.4", 2225 + "chai": "^5.2.0", 2226 + "debug": "^4.4.1", 2227 + "expect-type": "^1.2.1", 2228 + "magic-string": "^0.30.17", 2229 + "pathe": "^2.0.3", 2230 + "picomatch": "^4.0.2", 2231 + "std-env": "^3.9.0", 2232 + "tinybench": "^2.9.0", 2233 + "tinyexec": "^0.3.2", 2234 + "tinyglobby": "^0.2.14", 2235 + "tinypool": "^1.1.1", 2236 + "tinyrainbow": "^2.0.0", 2237 + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", 2238 + "vite-node": "3.2.4", 2239 + "why-is-node-running": "^2.3.0" 2240 + }, 2241 + "bin": { 2242 + "vitest": "vitest.mjs" 2243 + }, 2244 + "engines": { 2245 + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 2246 + }, 2247 + "funding": { 2248 + "url": "https://opencollective.com/vitest" 2249 + }, 2250 + "peerDependencies": { 2251 + "@edge-runtime/vm": "*", 2252 + "@types/debug": "^4.1.12", 2253 + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", 2254 + "@vitest/browser": "3.2.4", 2255 + "@vitest/ui": "3.2.4", 2256 + "happy-dom": "*", 2257 + "jsdom": "*" 2258 + }, 2259 + "peerDependenciesMeta": { 2260 + "@edge-runtime/vm": { 2261 + "optional": true 2262 + }, 2263 + "@types/debug": { 2264 + "optional": true 2265 + }, 2266 + "@types/node": { 2267 + "optional": true 2268 + }, 2269 + "@vitest/browser": { 2270 + "optional": true 2271 + }, 2272 + "@vitest/ui": { 2273 + "optional": true 2274 + }, 2275 + "happy-dom": { 2276 + "optional": true 2277 + }, 2278 + "jsdom": { 2279 + "optional": true 2280 + } 2281 + } 2282 + }, 2283 + "node_modules/which": { 2284 + "version": "2.0.2", 2285 + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2286 + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2287 + "dev": true, 2288 + "license": "ISC", 2289 + "dependencies": { 2290 + "isexe": "^2.0.0" 2291 + }, 2292 + "bin": { 2293 + "node-which": "bin/node-which" 2294 + }, 2295 + "engines": { 2296 + "node": ">= 8" 2297 + } 2298 + }, 2299 + "node_modules/why-is-node-running": { 2300 + "version": "2.3.0", 2301 + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", 2302 + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", 2303 + "dev": true, 2304 + "license": "MIT", 2305 + "dependencies": { 2306 + "siginfo": "^2.0.0", 2307 + "stackback": "0.0.2" 2308 + }, 2309 + "bin": { 2310 + "why-is-node-running": "cli.js" 2311 + }, 2312 + "engines": { 2313 + "node": ">=8" 2314 + } 2315 + }, 2316 + "node_modules/wrap-ansi": { 2317 + "version": "8.1.0", 2318 + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", 2319 + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", 2320 + "dev": true, 2321 + "license": "MIT", 2322 + "dependencies": { 2323 + "ansi-styles": "^6.1.0", 2324 + "string-width": "^5.0.1", 2325 + "strip-ansi": "^7.0.1" 2326 + }, 2327 + "engines": { 2328 + "node": ">=12" 2329 + }, 2330 + "funding": { 2331 + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 2332 + } 2333 + }, 2334 + "node_modules/wrap-ansi-cjs": { 2335 + "name": "wrap-ansi", 2336 + "version": "7.0.0", 2337 + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 2338 + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 2339 + "dev": true, 2340 + "license": "MIT", 2341 + "dependencies": { 2342 + "ansi-styles": "^4.0.0", 2343 + "string-width": "^4.1.0", 2344 + "strip-ansi": "^6.0.0" 2345 + }, 2346 + "engines": { 2347 + "node": ">=10" 2348 + }, 2349 + "funding": { 2350 + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 2351 + } 2352 + }, 2353 + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { 2354 + "version": "5.0.1", 2355 + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 2356 + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 2357 + "dev": true, 2358 + "license": "MIT", 2359 + "engines": { 2360 + "node": ">=8" 2361 + } 2362 + }, 2363 + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { 2364 + "version": "4.3.0", 2365 + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 2366 + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 2367 + "dev": true, 108 2368 "license": "MIT", 109 2369 "dependencies": { 110 - "tr46": "~0.0.3", 111 - "webidl-conversions": "^3.0.0" 2370 + "color-convert": "^2.0.1" 2371 + }, 2372 + "engines": { 2373 + "node": ">=8" 2374 + }, 2375 + "funding": { 2376 + "url": "https://github.com/chalk/ansi-styles?sponsor=1" 2377 + } 2378 + }, 2379 + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { 2380 + "version": "8.0.0", 2381 + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 2382 + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 2383 + "dev": true, 2384 + "license": "MIT" 2385 + }, 2386 + "node_modules/wrap-ansi-cjs/node_modules/string-width": { 2387 + "version": "4.2.3", 2388 + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 2389 + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 2390 + "dev": true, 2391 + "license": "MIT", 2392 + "dependencies": { 2393 + "emoji-regex": "^8.0.0", 2394 + "is-fullwidth-code-point": "^3.0.0", 2395 + "strip-ansi": "^6.0.1" 2396 + }, 2397 + "engines": { 2398 + "node": ">=8" 2399 + } 2400 + }, 2401 + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { 2402 + "version": "6.0.1", 2403 + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 2404 + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2405 + "dev": true, 2406 + "license": "MIT", 2407 + "dependencies": { 2408 + "ansi-regex": "^5.0.1" 2409 + }, 2410 + "engines": { 2411 + "node": ">=8" 112 2412 } 113 2413 } 114 2414 }
+15 -6
package.json
··· 1 1 { 2 2 "name": "morning-report", 3 - "version": "0.0.1", 3 + "version": "0.0.5", 4 4 "description": "Procedurally generates a radio weather report", 5 5 "keywords": [ 6 6 "weather", ··· 19 19 }, 20 20 "type": "module", 21 21 "main": "distribution/index.js", 22 + "bin": { 23 + "morning-report": "./distribution/src/index.js" 24 + }, 25 + "files": [ 26 + "distribution" 27 + ], 22 28 "scripts": { 23 - "build": "npx tsc", 24 - "start": "node distribution/index.js" 29 + "build": "tsc", 30 + "start": "node distribution/src/index.js", 31 + "test": "vitest" 25 32 }, 26 33 "dependencies": { 27 34 "json5": "2.2.3", 28 - "openweathermap-ts": "1.2.10" 35 + "openweather-api-node": "3.1.5" 29 36 }, 30 37 "devDependencies": { 31 - "typescript": "5.9.2", 32 - "@types/node": "24.3.0" 38 + "typescript": "5.9.3", 39 + "@types/node": "24.10.1", 40 + "vitest": "3.2.4", 41 + "@vitest/coverage-v8": "3.2.4" 33 42 } 34 43 }
+7 -3
src/index.ts
··· 1 + #!/usr/bin/env node 1 2 import path from 'path'; 2 3 import fsp from 'fs/promises'; 3 4 import json5 from 'json5'; 4 5 import Sequencer from './sequencer.js'; 6 + import { Stitcher } from './stitcher.js'; 5 7 import type {Programs, Segments, Sequences} from './sequencer.js'; 6 8 import type { Voices } from './voice.js'; 9 + import type { Options } from 'openweather-api-node'; 7 10 8 11 9 12 interface Config { 10 13 programs: Programs, 11 14 segments: Segments, 12 15 sequences: Sequences, 13 - voices: Voices 16 + voices: Voices, 17 + weather: Options 14 18 } 15 19 16 20 console.log('morning-report\nCory Sanin 2025\n'); 17 21 18 22 const config: Config = json5.parse(await fsp.readFile(process.env['CONFIG'] || path.join('config', 'config.json5'), { encoding: 'utf-8' })); 19 - const sequence = Sequencer(config); 23 + const sequence = await Sequencer(config); 20 24 console.log(sequence.join('\n')); 21 - 25 + await Stitcher(sequence); 22 26 23 27 export type { Config };
+72 -14
src/sequencer.ts
··· 1 + import { OpenWeatherAPI, type DailyWeather } from 'openweather-api-node'; 2 + import { voiceLines } from './voice.js'; 1 3 import type { Config } from './index.js'; 4 + import type { Voice } from './voice.js'; 5 + import crypto from 'crypto'; 2 6 3 7 type SegmentName = string; 4 8 type SequenceName = string; 5 9 type Programs = SegmentName[][]; 6 10 type Segments = { [segment: SegmentName]: SequenceName[] }; 7 11 type Sequence = { 8 - condition?: string; 12 + conditions?: string[]; 9 13 tracks: string[]; 10 14 } 11 15 type Sequences = { [sequence: SequenceName]: Sequence }; ··· 13 17 let config: Config = null; 14 18 15 19 function selectOne<T>(arr: T[]): T { 16 - return arr[Math.floor(Math.random() * arr.length)]; 20 + return arr[crypto.randomInt(0, arr.length)]; 21 + } 22 + 23 + function resolveSide(side: string, currentWeather: DailyWeather) { 24 + if (!side.startsWith('weather')) { 25 + return side.includes('.') ? parseFloat(side) : parseInt(side); 26 + } 27 + 28 + const tokens = side.split('.'); 29 + let w = currentWeather; 30 + tokens.forEach(t => w = w[t]); 31 + return typeof w === 'object' ? JSON.stringify(w) : w as (string | number); 32 + } 33 + 34 + function notNotANumber(something: number | string, defaultVal: string) { 35 + if (typeof something === 'string' || !isNaN(something)) { 36 + return something; 37 + } 38 + return defaultVal; 17 39 } 18 40 19 - function conditionIsMet(condition: string | undefined = undefined): boolean { 41 + function conditionIsMet(condition: string | undefined, currentWeather: DailyWeather): boolean { 20 42 if (typeof condition !== 'string') { 21 43 return true; 22 44 } 23 - // TODO: parse condition, return bool 24 - return false; 45 + const [lhs, relational, rhs] = condition.split(' '); 46 + if (lhs === undefined || relational === undefined || rhs === undefined) { 47 + throw new Error(`Condition "${condition}" is not in the correct format`); 48 + } 49 + const lhsResolved = notNotANumber(resolveSide(lhs, currentWeather), lhs); 50 + const rhsResolved = notNotANumber(resolveSide(rhs, currentWeather), rhs); 51 + switch (relational) { 52 + case '=': 53 + case '==': 54 + return lhsResolved == rhsResolved; 55 + case '!=': 56 + return lhsResolved != rhsResolved; 57 + case '<': 58 + return lhsResolved < rhsResolved; 59 + case '<=': 60 + return lhsResolved <= rhsResolved; 61 + case '>': 62 + return lhsResolved > rhsResolved; 63 + case '>=': 64 + return lhsResolved >= rhsResolved; 65 + default: 66 + throw new Error(`Unsupported relational operator: ${relational}`); 67 + } 25 68 } 26 69 27 - function processSequence(sequence: Sequence): string[] { 70 + function resolveMacro(str: string, currentWeather: DailyWeather): string[] { 71 + if (str.startsWith('%')) { 72 + const [profile, subject] = str.substring(1).split(' ', 2); 73 + const voiceProfile: Voice = config.voices[profile]; 74 + let resolvedSubject: any = currentWeather; 75 + subject.split('.').forEach(t => resolvedSubject = resolvedSubject[t]); 76 + return voiceLines(voiceProfile, resolvedSubject); 77 + } 78 + return [str]; 79 + } 80 + 81 + function processSequence(sequence: Sequence, currentWeather: DailyWeather): string[] { 28 82 const tracks = sequence.tracks; 29 - // TODO: process voice macros 30 - return tracks; 83 + return tracks.map(t => resolveMacro(t, currentWeather)).flat().filter(t => t !== null); 31 84 } 32 85 33 - function processSegment(segment: SegmentName): string[] { 86 + function processSegment(segment: SegmentName, currentWeather: DailyWeather): string[] { 34 87 if (!(segment in config.segments)) { 35 - return processSequence(config.sequences[segment]); 88 + return (config.sequences[segment].conditions || []).every(c => conditionIsMet(c, currentWeather)) ? processSequence(config.sequences[segment], currentWeather) : []; 36 89 } 37 - const potentialSequences: SequenceName[] = config.segments[segment].filter(s => conditionIsMet(config.sequences[s].condition)); 90 + const potentialSequences: SequenceName[] = config.segments[segment].filter(s => (config.sequences[s].conditions || []).every(c => conditionIsMet(c, currentWeather))); 38 91 if (potentialSequences.length === 0) { 39 92 return []; 40 93 } 41 - return processSequence(config.sequences[selectOne(potentialSequences)]); 94 + return processSequence(config.sequences[selectOne(potentialSequences)], currentWeather); 42 95 } 43 96 44 - function Sequencer(conf: Config): string[] { 97 + async function Sequencer(conf: Config): Promise<string[]> { 45 98 config = conf; 99 + const weather = new OpenWeatherAPI(conf.weather); 100 + const currentWeather = await weather.getToday(); 46 101 const sequence: string[] = []; 47 102 const program: SegmentName[] = selectOne(conf.programs); 48 - program.forEach(segment => sequence.push(...processSegment(segment))); 103 + for (let i = 0; i < program.length; i++) { 104 + const segment = program[i]; 105 + sequence.push(...(processSegment(segment, currentWeather))); 106 + } 49 107 return sequence; 50 108 } 51 109
+34
src/stitcher.ts
··· 1 + import { spawn } from 'child_process'; 2 + 3 + const ENCTOOL = process.env['ENCTOOL'] || 'ffmpeg'; 4 + 5 + function ffmpeg(args: string[], files: number): Promise<void> { 6 + return new Promise((resolve, reject) => { 7 + console.log(`${ENCTOOL} ${args.join(' ')}`); 8 + const process = spawn(ENCTOOL, args); 9 + const to = setTimeout(async () => { 10 + process.kill(); 11 + reject(new Error('timed out')); 12 + }, 5000 * files); 13 + process.on('exit', async (code) => { 14 + clearTimeout(to); 15 + if (code !== 0) { 16 + reject(new Error(`exited with ${code}`)); 17 + } 18 + else { 19 + resolve(); 20 + } 21 + }); 22 + }); 23 + } 24 + 25 + async function Stitcher(files: string[]) { 26 + const args: string[] = []; 27 + files.forEach(f => args.push('-i', f)); 28 + args.push('-filter_complex', `[0:a][1:a][2:a]concat=n=${files.length}:v=0:a=1[out]`); 29 + args.push('-map', '[out]', '-ar', '44100', '-ac', '2', '-c:a', 'pcm_s16le', 'output.wav', '-y'); 30 + await ffmpeg(args, files.length); 31 + } 32 + 33 + export default Stitcher; 34 + export { Stitcher };
+161 -1
src/voice.ts
··· 1 - 1 + import path from 'path'; 2 2 3 3 interface Voice { 4 4 directory: string; ··· 7 7 8 8 type Voices = { [name: string]: Voice }; 9 9 10 + const LINES = { 11 + NEGATIVE: 'negative', 12 + POINT: 'point', 13 + ZERO: 'zero', 14 + ONE: 'one', 15 + TWO: 'two', 16 + THREE: 'three', 17 + FOUR: 'four', 18 + FIVE: 'five', 19 + SIX: 'six', 20 + SEVEN: 'seven', 21 + EIGHT: 'eight', 22 + NINE: 'nine', 23 + TEN: 'ten', 24 + ELEVEN: 'eleven', 25 + TWELVE: 'twelve', 26 + THIRTEEN: 'thirteen', 27 + FIFTEEN: 'fifteen', 28 + TEEN: 'teen', 29 + TWENTY: 'twenty', 30 + THIRTY: 'thirty', 31 + FORTY: 'forty', 32 + FIFTY: 'fifty', 33 + SIXTY: 'sixty', 34 + SEVENTY: 'seventy', 35 + EIGHTY: 'eighty', 36 + NINETY: 'ninety', 37 + HUNDRED: 'hundred', 38 + THOUSAND: 'thousand', 39 + MILLION: 'million', 40 + BILLION: 'billion', 41 + TRILLION: 'trillion' 42 + } 43 + 44 + function formatNumber(num: number): string { 45 + const parts = num.toString().split("."); 46 + parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ","); 47 + return parts.join("."); 48 + } 49 + 50 + function digitByDigit(str: string): string[] { 51 + const tokens: string[] = []; 52 + const input = str.replaceAll(',', ''); 53 + const map = [ 54 + LINES.ZERO, 55 + LINES.ONE, 56 + LINES.TWO, 57 + LINES.THREE, 58 + LINES.FOUR, 59 + LINES.FIVE, 60 + LINES.SIX, 61 + LINES.SEVEN, 62 + LINES.EIGHT, 63 + LINES.NINE 64 + ] 65 + for (let i = 0; i < input.length; i++) { 66 + tokens.push(map[parseInt(input.charAt(i))]); 67 + } 68 + return tokens; 69 + } 70 + 71 + function tens(str: string): string[] { 72 + if (str === '0') { 73 + return [LINES.ZERO]; 74 + } 75 + const tokens: string[] = []; 76 + const num = parseInt(str); 77 + const map = { 78 + '2': LINES.TWENTY, 79 + '3': LINES.THIRTY, 80 + '4': LINES.FORTY, 81 + '5': LINES.FIFTY, 82 + '6': LINES.SIXTY, 83 + '7': LINES.SEVENTY, 84 + '8': LINES.EIGHTY, 85 + '9': LINES.NINETY 86 + }; 87 + const ones = str.charAt(str.length - 1); 88 + if (num === 0) { 89 + return []; 90 + } 91 + else if (num >= 20) { 92 + tokens.push(map[str.charAt(0)]); 93 + if (ones !== '0') { 94 + tokens.push(...digitByDigit(ones)); 95 + } 96 + } 97 + else if (num < 10) { 98 + tokens.push(...digitByDigit(ones)); 99 + } 100 + else { 101 + const weirdoNumberMap = [ 102 + [LINES.TEN], 103 + [LINES.ELEVEN], 104 + [LINES.TWELVE], 105 + [LINES.THIRTEEN], 106 + [LINES.FOUR, LINES.TEEN], 107 + [LINES.FIFTEEN], 108 + [LINES.SIX, LINES.TEEN], 109 + [LINES.SEVEN, LINES.TEEN], 110 + [LINES.EIGHT, LINES.TEEN], 111 + [LINES.NINE, LINES.TEEN], 112 + ] 113 + tokens.push(...weirdoNumberMap[num - 10]); 114 + } 115 + return tokens; 116 + } 117 + 118 + function hundreds(str: string): string[] { 119 + const tokens: string[] = []; 120 + if (str.length === 3 && str.charAt(0) !== '0') { 121 + tokens.push(...digitByDigit(str.charAt(0))); 122 + tokens.push(LINES.HUNDRED); 123 + str = str.substring(1); 124 + } 125 + tokens.push(...tens(str)); 126 + return tokens; 127 + } 128 + 129 + function integer(str: string): string[] { 130 + const tokens: string[] = []; 131 + const numGroups = str.split(','); 132 + const seperators = [LINES.TRILLION, LINES.BILLION, LINES.MILLION, LINES.THOUSAND]; 133 + seperators.splice(0, seperators.length - numGroups.length + 1); 134 + numGroups.forEach(g => { 135 + if (g !== '000') { 136 + tokens.push(...hundreds(g)); 137 + } 138 + if (seperators.length === 0) { 139 + return; 140 + } 141 + const sep = seperators.shift(); 142 + if (g !== '000') { 143 + tokens.push(sep); 144 + } 145 + }); 146 + return tokens; 147 + } 148 + 149 + function voiceLines(voice: Voice, num: number): string[] { 150 + if (Math.abs(num) > 999999999999999 || isNaN(num)) { 151 + return []; 152 + } 153 + const tokens: string[] = []; 154 + const str = formatNumber(num); 155 + const parts = str.split('.'); 156 + if (parts[0].startsWith('-')) { 157 + tokens.push(LINES.NEGATIVE); 158 + parts[0] = parts[0].substring(1); 159 + } 160 + tokens.push(...integer(parts[0])); 161 + if (parts.length > 1) { 162 + tokens.push(LINES.POINT); 163 + tokens.push(...digitByDigit(parts[1])); 164 + } 165 + return tokens.map(l => path.join(voice.directory, `${l}${voice.extension.length > 0 && voice.extension.charAt(0) !== '.' ? '.' : ''}${voice.extension}`)); 166 + } 167 + 168 + export default voiceLines; 169 + export { voiceLines, LINES }; 10 170 export type { Voice, Voices };
src/weather.ts

This is a binary file and will not be displayed.

+189
test/sequencer.test.ts
··· 1 + import { describe, expect, it, vi } from 'vitest'; 2 + import { type Options } from 'openweather-api-node'; 3 + import { Sequencer } from '../src/sequencer.js'; 4 + 5 + const dummyWeather: Options = { key: 'dummy' }; 6 + 7 + vi.mock('openweather-api-node', () => { 8 + return { 9 + OpenWeatherAPI: vi.fn().mockImplementation((_) => { 10 + return { 11 + getToday: vi.fn(() => { 12 + return { 13 + "lat": 43.0748, 14 + "lon": -89.3838, 15 + "dt": "2025-08-29T06:31:05.000Z", 16 + "dtRaw": 1756449065, 17 + "timezoneOffset": -18000, 18 + "astronomical": { 19 + "sunrise": "2025-08-29T11:19:05.000Z", 20 + "sunriseRaw": 1756466345, 21 + "sunset": "2025-08-30T00:38:08.000Z", 22 + "sunsetRaw": 1756514288 23 + }, 24 + "weather": { 25 + "temp": { 26 + "cur": 55.85, 27 + "min": 52.99, 28 + "max": 58.01 29 + }, 30 + "feelsLike": { 31 + "cur": 55.31 32 + }, 33 + "pressure": 1022, 34 + "humidity": 89, 35 + "clouds": 0, 36 + "visibility": 10000, 37 + "wind": { 38 + "deg": 140, 39 + "speed": 5.75 40 + }, 41 + "rain": 0, 42 + "snow": 0, 43 + "conditionId": 800, 44 + "main": "Clear", 45 + "description": "clear sky", 46 + "icon": { 47 + "url": "http://openweathermap.org/img/wn/01n@2x.png", 48 + "raw": "01n" 49 + } 50 + } 51 + } 52 + }) 53 + } 54 + }) 55 + } 56 + }); 57 + 58 + describe('sequencer', () => { 59 + it('can generate a list from a static config', async () => { 60 + expect(await Sequencer({ 61 + programs: [['sequence 1', 'segment 1', 'segment 2']], 62 + segments: { 63 + 'segment 1': ['sequence 1'], 64 + 'segment 2': ['sequence 2'] 65 + }, 66 + sequences: { 67 + 'sequence 1': { 68 + 'tracks': [ 69 + 'seq1.flac' 70 + ] 71 + }, 72 + 'sequence 2': { 73 + 'tracks': [ 74 + 'seq2.flac' 75 + ] 76 + } 77 + }, 78 + voices: {}, 79 + weather: dummyWeather 80 + })).to.include.ordered.members(['seq1.flac', 'seq1.flac', 'seq2.flac']); 81 + }); 82 + 83 + it('can include tracks conditionally', async () => { 84 + expect(await Sequencer({ 85 + programs: [['segment 1', 'sequence 1', 'segment 2', 'sequence 2']], 86 + segments: { 87 + 'segment 1': ['sequence 1'], 88 + 'segment 2': ['sequence 2'] 89 + }, 90 + sequences: { 91 + 'sequence 1': { 92 + 'conditions': ['1 = 1', '1.1 > 1', '2 >= 1', '1 < 2', '1 <= 1', '-1 != 0', undefined], 93 + 'tracks': [ 94 + 'seq1.flac' 95 + ] 96 + }, 97 + 'sequence 2': { 98 + 'conditions': ['weather.lat = -500'], 99 + 'tracks': [ 100 + 'seq2.flac' 101 + ] 102 + } 103 + }, 104 + voices: {}, 105 + weather: dummyWeather 106 + })).to.be.ordered.members(['seq1.flac', 'seq1.flac']); 107 + }); 108 + 109 + it('throws an error on invalid conditions', async () => { 110 + await expect(Sequencer({ 111 + programs: [['sequence 1']], 112 + segments: { 113 + }, 114 + sequences: { 115 + 'sequence 1': { 116 + 'conditions': ['100'], 117 + 'tracks': [ 118 + 'seq1.flac' 119 + ] 120 + } 121 + }, 122 + voices: {}, 123 + weather: dummyWeather 124 + })).rejects.toThrow(/not in the correct format/); 125 + 126 + await expect(Sequencer({ 127 + programs: [['sequence 1']], 128 + segments: { 129 + }, 130 + sequences: { 131 + 'sequence 1': { 132 + 'conditions': ['1 ~ 2'], 133 + 'tracks': [ 134 + 'seq1.flac' 135 + ] 136 + } 137 + }, 138 + voices: {}, 139 + weather: dummyWeather 140 + })).rejects.toThrow(/Unsupported relational operator/); 141 + }); 142 + 143 + it('can stringify conditions', async () => { 144 + expect(await Sequencer({ 145 + programs: [['sequence 1']], 146 + segments: { 147 + }, 148 + sequences: { 149 + 'sequence 1': { 150 + 'conditions': ['weather.feelsLike = {"cur":55.31}'], 151 + 'tracks': [ 152 + 'seq1.flac' 153 + ] 154 + } 155 + }, 156 + voices: {}, 157 + weather: dummyWeather 158 + })).to.be.ordered.members(['seq1.flac']); 159 + }); 160 + 161 + it('can parse voice macros', async () => { 162 + expect(await Sequencer({ 163 + programs: [['sequence 1']], 164 + segments: { 165 + }, 166 + sequences: { 167 + 'sequence 1': { 168 + 'tracks': [ 169 + '%alice weather.temp.max' 170 + ] 171 + } 172 + }, 173 + voices: { 174 + "alice": { 175 + "directory": "alice/", 176 + "extension": "flac" 177 + } 178 + }, 179 + weather: dummyWeather 180 + })).to.be.ordered.members([ 181 + 'alice/fifty.flac', 182 + 'alice/eight.flac', 183 + 'alice/point.flac', 184 + 'alice/zero.flac', 185 + 'alice/one.flac' 186 + ]); 187 + }); 188 + }); 189 +
+90
test/stitcher.test.ts
··· 1 + import { Stitcher } from '../src/stitcher.js'; 2 + import { describe, expect, it, vi, beforeEach } from 'vitest'; 3 + import { EventEmitter } from 'events'; 4 + import { spawn } from 'child_process'; 5 + 6 + const mockChildProcess = new (class MockChildProcess 7 + extends EventEmitter { 8 + kill = vi.fn(() => { 9 + return true; 10 + }); 11 + })(); 12 + 13 + vi.mock('child_process', () => { 14 + return { 15 + spawn: vi.fn(() => mockChildProcess) 16 + } 17 + }); 18 + 19 + describe('stitcher', () => { 20 + 21 + beforeEach(() => { 22 + vi.clearAllMocks(); 23 + }); 24 + 25 + it('passes the correct arguments to ffmpeg', async () => { 26 + const p = Stitcher(['1.flac', 'dir/2.flac']); 27 + mockChildProcess.emit('exit', 0, null); 28 + await p; 29 + expect(spawn).toBeCalledWith('ffmpeg', [ 30 + "-i", 31 + '1.flac', 32 + '-i', 33 + 'dir/2.flac', 34 + '-filter_complex', 35 + '[0:a][1:a][2:a]concat=n=2:v=0:a=1[out]', 36 + '-map', 37 + '[out]', 38 + '-ar', 39 + '44100', 40 + '-ac', 41 + '2', 42 + '-c:a', 43 + 'pcm_s16le', 44 + 'output.wav', 45 + '-y' 46 + ]); 47 + }); 48 + 49 + it('throws an error when ffmpeg fails', async () => { 50 + const p = Stitcher(['sound.mp3']); 51 + mockChildProcess.emit('exit', 1, null); 52 + await expect(p).rejects.toThrow('exited with 1'); 53 + expect(spawn).toBeCalledWith('ffmpeg', [ 54 + "-i", 55 + 'sound.mp3', 56 + '-filter_complex', 57 + '[0:a][1:a][2:a]concat=n=1:v=0:a=1[out]', 58 + '-map', 59 + '[out]', 60 + '-ar', 61 + '44100', 62 + '-ac', 63 + '2', 64 + '-c:a', 65 + 'pcm_s16le', 66 + 'output.wav', 67 + '-y' 68 + ]); 69 + }); 70 + 71 + it('throws an error when ffmpeg takes longer than expected', { timeout: 6000 }, async () => { 72 + await expect(Stitcher(['in.wav'])).rejects.toThrow('timed out'); 73 + expect(spawn).toBeCalledWith('ffmpeg', [ 74 + "-i", 75 + 'in.wav', 76 + '-filter_complex', 77 + '[0:a][1:a][2:a]concat=n=1:v=0:a=1[out]', 78 + '-map', 79 + '[out]', 80 + '-ar', 81 + '44100', 82 + '-ac', 83 + '2', 84 + '-c:a', 85 + 'pcm_s16le', 86 + 'output.wav', 87 + '-y' 88 + ]); 89 + }); 90 + });
+129
test/voice.test.ts
··· 1 + import path from 'path'; 2 + import { describe, expect, it } from 'vitest'; 3 + import { voiceLines, LINES } from '../src/voice.js'; 4 + import type { Voice } from '../src/voice.js'; 5 + 6 + const dummyVoice: Voice = { 7 + 'directory': '', 8 + 'extension': '' 9 + }; 10 + 11 + describe('voiceLines', () => { 12 + it('handles integers', () => { 13 + expect(voiceLines(dummyVoice, 16549872)).to.be.ordered.members( 14 + [ 15 + LINES.SIX, LINES.TEEN, LINES.MILLION, LINES.FIVE, LINES.HUNDRED, LINES.FORTY, 16 + LINES.NINE, LINES.THOUSAND, LINES.EIGHT, LINES.HUNDRED, LINES.SEVENTY, LINES.TWO 17 + ] 18 + ); 19 + }); 20 + 21 + it('handles floating point', () => { 22 + expect(voiceLines(dummyVoice, 672.09435)).to.be.ordered.members( 23 + [ 24 + LINES.SIX, LINES.HUNDRED, LINES.SEVENTY, LINES.TWO, LINES.POINT, LINES.ZERO, 25 + LINES.NINE, LINES.FOUR, LINES.THREE, LINES.FIVE 26 + ] 27 + ); 28 + }); 29 + 30 + it('handles the negative', () => { 31 + expect(voiceLines(dummyVoice, -672.09435)).to.be.ordered.members( 32 + [ 33 + LINES.NEGATIVE, LINES.SIX, LINES.HUNDRED, LINES.SEVENTY, LINES.TWO, LINES.POINT, LINES.ZERO, 34 + LINES.NINE, LINES.FOUR, LINES.THREE, LINES.FIVE 35 + ] 36 + ); 37 + }); 38 + 39 + it('handles zero', () => { 40 + expect(voiceLines(dummyVoice, 0)).to.be.ordered.members( 41 + [ 42 + LINES.ZERO 43 + ] 44 + ); 45 + }); 46 + 47 + it('handles large numbers with many zeroes', () => { 48 + expect(voiceLines(dummyVoice, 700000000000001)).to.be.ordered.members( 49 + [ 50 + LINES.SEVEN, LINES.HUNDRED, LINES.TRILLION, LINES.ONE 51 + ] 52 + ); 53 + 54 + expect(voiceLines(dummyVoice, 1000001)).to.be.ordered.members( 55 + [ 56 + LINES.ONE, LINES.MILLION, LINES.ONE 57 + ] 58 + ); 59 + 60 + expect(voiceLines(dummyVoice, 9000000001000)).to.be.ordered.members( 61 + [ 62 + LINES.NINE, LINES.TRILLION, LINES.ONE, LINES.THOUSAND 63 + ] 64 + ); 65 + 66 + expect(voiceLines(dummyVoice, 60002000000000.12)).to.be.ordered.members( 67 + [ 68 + LINES.SIXTY, LINES.TRILLION, LINES.TWO, LINES.BILLION, LINES.POINT, LINES.ONE, LINES.TWO 69 + ] 70 + ); 71 + 72 + expect(voiceLines(dummyVoice, 100010001)).to.be.ordered.members( 73 + [ 74 + LINES.ONE, LINES.HUNDRED, LINES.MILLION, LINES.TEN, LINES.THOUSAND, LINES.ONE 75 + ] 76 + ); 77 + }); 78 + 79 + it('handles irregularly named numbers', () => { 80 + expect(voiceLines(dummyVoice, 210)).to.be.ordered.members( 81 + [ 82 + LINES.TWO, LINES.HUNDRED, LINES.TEN 83 + ] 84 + ); 85 + 86 + expect(voiceLines(dummyVoice, 311)).to.be.ordered.members( 87 + [ 88 + LINES.THREE, LINES.HUNDRED, LINES.ELEVEN 89 + ] 90 + ); 91 + 92 + expect(voiceLines(dummyVoice, 412)).to.be.ordered.members( 93 + [ 94 + LINES.FOUR, LINES.HUNDRED, LINES.TWELVE 95 + ] 96 + ); 97 + 98 + expect(voiceLines(dummyVoice, 513)).to.be.ordered.members( 99 + [ 100 + LINES.FIVE, LINES.HUNDRED, LINES.THIRTEEN 101 + ] 102 + ); 103 + 104 + expect(voiceLines(dummyVoice, 615)).to.be.ordered.members( 105 + [ 106 + LINES.SIX, LINES.HUNDRED, LINES.FIFTEEN 107 + ] 108 + ); 109 + }); 110 + 111 + it('returns empty array if value is unsupported', () => { 112 + expect(voiceLines(dummyVoice, Infinity)).length.to.be.empty; 113 + expect(voiceLines(dummyVoice, -Infinity)).length.to.be.empty; 114 + expect(voiceLines(dummyVoice, NaN)).length.to.be.empty; 115 + expect(voiceLines(dummyVoice, 1e21)).length.to.be.empty; 116 + }); 117 + 118 + it('returns the results as paths when voice configuration is provided', () => { 119 + const directory = path.join('audio', 'voice', 'someone'); 120 + const v: Voice = { 121 + directory, 122 + extension: 'flac' 123 + } 124 + expect(voiceLines(v, 29)).to.be.ordered.members([ 125 + path.join(directory, `twenty.flac`), 126 + path.join(directory, `nine.flac`), 127 + ]); 128 + }); 129 + });
+2 -2
tsconfig.json
··· 9 9 "moduleResolution": "node16", 10 10 "sourceMap": true, 11 11 "inlineSources": true, 12 - "rootDir": "./src", 12 + "rootDir": "./", 13 13 "outDir": "./distribution" 14 14 }, 15 - "include": ["src/**/*"], 15 + "include": ["src/**/*", "test/**/*"], 16 16 "exclude": ["**/*.spec.ts"] 17 17 }