├── .github └── workflows │ ├── renovate-checks.yml │ └── section-repos.yml ├── .gitignore ├── .nvmrc ├── .vscode └── settings.json ├── README.md ├── package-lock.json ├── package.json ├── renovate.json ├── src ├── 01-number.problem.ts ├── 01-number.solution.ts ├── 02-object.problem.ts ├── 02-object.solution.ts ├── 03-array.problem.ts ├── 03-array.solution.ts ├── 04-infer.problem.ts ├── 04-infer.solution.1.ts ├── 04-infer.solution.2.ts ├── 05-optional.problem.ts ├── 05-optional.solution.ts ├── 06-default.problem.ts ├── 06-default.solution.ts ├── 07-union.problem.ts ├── 07-union.solution.1.ts ├── 07-union.solution.2.ts ├── 08-validations.problem.ts ├── 08-validations.solution.ts ├── 09-composing-objects.problem.ts ├── 09-composing-objects.solution.1.ts ├── 09-composing-objects.solution.2.ts ├── 09-composing-objects.solution.3.ts ├── 10-transform.problem.ts ├── 10-transform.solution.ts └── helpers │ └── type-utils.ts ├── tsconfig.json └── vite.config.mts /.github/workflows/renovate-checks.yml: -------------------------------------------------------------------------------- 1 | name: Renovate Checks 2 | on: 3 | push: 4 | branches: 5 | - "renovate/**" 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout Main 12 | uses: actions/checkout@v4 13 | with: 14 | ref: main 15 | path: repo 16 | 17 | - name: Install Dependencies in Main 18 | run: (cd repo && npm install) 19 | - name: Create Snapshot In Main 20 | run: (cd repo && npx tt-cli take-snapshot ./snap.md) 21 | - name: Copy Snapshot To Outer Directory 22 | run: mv repo/snap.md ./snap.md 23 | - name: Delete Main Directory 24 | run: rm -rf repo 25 | - name: Checkout Branch 26 | uses: actions/checkout@v4 27 | with: 28 | path: repo 29 | - name: Install Dependencies in Branch 30 | run: (cd repo && npm install) 31 | - name: Move Snapshot To Branch 32 | run: mv ./snap.md repo/snap.md 33 | - name: Compare Snapshot In Branch 34 | run: (cd repo && npx tt-cli compare-snapshot ./snap.md) 35 | -------------------------------------------------------------------------------- /.github/workflows/section-repos.yml: -------------------------------------------------------------------------------- 1 | name: Create Section Repos 2 | on: 3 | push: 4 | branches: 5 | - "main" 6 | 7 | concurrency: 8 | group: ${{ github.workflow }}-${{ github.ref }} 9 | cancel-in-progress: true 10 | 11 | jobs: 12 | run: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v4 16 | - uses: actions/setup-node@v4 17 | with: 18 | node-version: 20.x 19 | - run: git config --global user.email "total-typescript@bot.com" 20 | - run: git config --global user.name "Total TypeScript Bot" 21 | - run: npx @total-typescript/exercise-cli@latest create-section-repos 22 | env: 23 | GITHUB_TOKEN: ${{ secrets.MY_GITHUB_TOKEN }} 24 | GH_TOKEN: ${{ secrets.MY_GITHUB_TOKEN }} 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | tsconfig.temp.json 3 | dist 4 | *.tsbuildinfo 5 | *.prompt.* 6 | .vscode/*.code-snippets -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 20.10.0 -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib", 3 | "typescript.enablePromptUseWorkspaceTsdk": true, 4 | "github.copilot.enable": { 5 | "*": false, 6 | }, 7 | "explorer.sortOrder": "mixed", 8 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Zod Tutorial 2 | 3 | zod tutorialWatch on TotalTypeScript.com 4 | 5 | This Zod tutorial will give you everything you ever needed to know about [Zod](https://github.com/colinhacks/zod) - an amazing library for building type-safe AND runtime-safe applications. 6 | 7 | ```sh 8 | # Installs all dependencies 9 | npm install 10 | 11 | # Asks you which exercise you'd like to run, and runs it 12 | npm run exercise 13 | ``` 14 | 15 | ## How to take the course 16 | 17 | You'll notice that the course is split into exercises. Each exercise is split into a `*.problem` and a `*.solution`. 18 | 19 | To take an exercise: 20 | 21 | 1. Run `npm run exercise` 22 | 2. Choose which exercise you'd like to run. 23 | 24 | This course encourages **active, exploratory learning**. In the video, I'll explain a problem, and **you'll be asked to try to find a solution**. To attempt a solution, you'll need to: 25 | 26 | 1. Check out [Zod's docs](https://zod.dev/). 27 | 1. Try to find something that looks relevant. 28 | 1. Give it a go to see if it solves the problem. 29 | 30 | You'll know if you've succeeded because the tests will pass. 31 | 32 | **If you succeed**, or **if you get stuck**, unpause the video and check out the `*.solution`. You can see if your solution is better or worse than mine! 33 | 34 | ## Acknowledgements 35 | 36 | Say thanks to Matt on [Twitter](https://twitter.com/mattpocockuk) or by joining his [Discord](https://discord.gg/8S5ujhfTB3). Consider signing up to his [Total TypeScript course](https://totaltypescript.com). 37 | 38 | ## Reference 39 | 40 | ### `npm run exercise` 41 | 42 | Alias: `npm run e` 43 | 44 | Open a prompt for choosing which exercise you'd like to run. 45 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zod-tutorial", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "zod-tutorial", 9 | "version": "1.0.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "zod": "^3.23.8" 13 | }, 14 | "devDependencies": { 15 | "@total-typescript/exercise-cli": "^0.11.0", 16 | "@types/node": "^18.6.5", 17 | "jsdom": "^25.0.0", 18 | "typescript": "^5.6.2", 19 | "vite-tsconfig-paths": "^5.1.4", 20 | "vitest": "^3.0.5" 21 | } 22 | }, 23 | "node_modules/@asamuzakjp/css-color": { 24 | "version": "2.8.3", 25 | "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-2.8.3.tgz", 26 | "integrity": "sha512-GIc76d9UI1hCvOATjZPyHFmE5qhRccp3/zGfMPapK3jBi+yocEzp6BBB0UnfRYP9NP4FANqUZYb0hnfs3TM3hw==", 27 | "dev": true, 28 | "license": "MIT", 29 | "dependencies": { 30 | "@csstools/css-calc": "^2.1.1", 31 | "@csstools/css-color-parser": "^3.0.7", 32 | "@csstools/css-parser-algorithms": "^3.0.4", 33 | "@csstools/css-tokenizer": "^3.0.3", 34 | "lru-cache": "^10.4.3" 35 | } 36 | }, 37 | "node_modules/@csstools/color-helpers": { 38 | "version": "5.0.1", 39 | "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.1.tgz", 40 | "integrity": "sha512-MKtmkA0BX87PKaO1NFRTFH+UnkgnmySQOvNxJubsadusqPEC2aJ9MOQiMceZJJ6oitUl/i0L6u0M1IrmAOmgBA==", 41 | "dev": true, 42 | "funding": [ 43 | { 44 | "type": "github", 45 | "url": "https://github.com/sponsors/csstools" 46 | }, 47 | { 48 | "type": "opencollective", 49 | "url": "https://opencollective.com/csstools" 50 | } 51 | ], 52 | "license": "MIT-0", 53 | "engines": { 54 | "node": ">=18" 55 | } 56 | }, 57 | "node_modules/@csstools/css-calc": { 58 | "version": "2.1.1", 59 | "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.1.tgz", 60 | "integrity": "sha512-rL7kaUnTkL9K+Cvo2pnCieqNpTKgQzy5f+N+5Iuko9HAoasP+xgprVh7KN/MaJVvVL1l0EzQq2MoqBHKSrDrag==", 61 | "dev": true, 62 | "funding": [ 63 | { 64 | "type": "github", 65 | "url": "https://github.com/sponsors/csstools" 66 | }, 67 | { 68 | "type": "opencollective", 69 | "url": "https://opencollective.com/csstools" 70 | } 71 | ], 72 | "license": "MIT", 73 | "engines": { 74 | "node": ">=18" 75 | }, 76 | "peerDependencies": { 77 | "@csstools/css-parser-algorithms": "^3.0.4", 78 | "@csstools/css-tokenizer": "^3.0.3" 79 | } 80 | }, 81 | "node_modules/@csstools/css-color-parser": { 82 | "version": "3.0.7", 83 | "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.7.tgz", 84 | "integrity": "sha512-nkMp2mTICw32uE5NN+EsJ4f5N+IGFeCFu4bGpiKgb2Pq/7J/MpyLBeQ5ry4KKtRFZaYs6sTmcMYrSRIyj5DFKA==", 85 | "dev": true, 86 | "funding": [ 87 | { 88 | "type": "github", 89 | "url": "https://github.com/sponsors/csstools" 90 | }, 91 | { 92 | "type": "opencollective", 93 | "url": "https://opencollective.com/csstools" 94 | } 95 | ], 96 | "license": "MIT", 97 | "dependencies": { 98 | "@csstools/color-helpers": "^5.0.1", 99 | "@csstools/css-calc": "^2.1.1" 100 | }, 101 | "engines": { 102 | "node": ">=18" 103 | }, 104 | "peerDependencies": { 105 | "@csstools/css-parser-algorithms": "^3.0.4", 106 | "@csstools/css-tokenizer": "^3.0.3" 107 | } 108 | }, 109 | "node_modules/@csstools/css-parser-algorithms": { 110 | "version": "3.0.4", 111 | "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", 112 | "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", 113 | "dev": true, 114 | "funding": [ 115 | { 116 | "type": "github", 117 | "url": "https://github.com/sponsors/csstools" 118 | }, 119 | { 120 | "type": "opencollective", 121 | "url": "https://opencollective.com/csstools" 122 | } 123 | ], 124 | "license": "MIT", 125 | "engines": { 126 | "node": ">=18" 127 | }, 128 | "peerDependencies": { 129 | "@csstools/css-tokenizer": "^3.0.3" 130 | } 131 | }, 132 | "node_modules/@csstools/css-tokenizer": { 133 | "version": "3.0.3", 134 | "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", 135 | "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", 136 | "dev": true, 137 | "funding": [ 138 | { 139 | "type": "github", 140 | "url": "https://github.com/sponsors/csstools" 141 | }, 142 | { 143 | "type": "opencollective", 144 | "url": "https://opencollective.com/csstools" 145 | } 146 | ], 147 | "license": "MIT", 148 | "engines": { 149 | "node": ">=18" 150 | } 151 | }, 152 | "node_modules/@esbuild/aix-ppc64": { 153 | "version": "0.24.2", 154 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", 155 | "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", 156 | "cpu": [ 157 | "ppc64" 158 | ], 159 | "dev": true, 160 | "license": "MIT", 161 | "optional": true, 162 | "os": [ 163 | "aix" 164 | ], 165 | "engines": { 166 | "node": ">=18" 167 | } 168 | }, 169 | "node_modules/@esbuild/android-arm": { 170 | "version": "0.24.2", 171 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", 172 | "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", 173 | "cpu": [ 174 | "arm" 175 | ], 176 | "dev": true, 177 | "license": "MIT", 178 | "optional": true, 179 | "os": [ 180 | "android" 181 | ], 182 | "engines": { 183 | "node": ">=18" 184 | } 185 | }, 186 | "node_modules/@esbuild/android-arm64": { 187 | "version": "0.24.2", 188 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", 189 | "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", 190 | "cpu": [ 191 | "arm64" 192 | ], 193 | "dev": true, 194 | "license": "MIT", 195 | "optional": true, 196 | "os": [ 197 | "android" 198 | ], 199 | "engines": { 200 | "node": ">=18" 201 | } 202 | }, 203 | "node_modules/@esbuild/android-x64": { 204 | "version": "0.24.2", 205 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", 206 | "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", 207 | "cpu": [ 208 | "x64" 209 | ], 210 | "dev": true, 211 | "license": "MIT", 212 | "optional": true, 213 | "os": [ 214 | "android" 215 | ], 216 | "engines": { 217 | "node": ">=18" 218 | } 219 | }, 220 | "node_modules/@esbuild/darwin-arm64": { 221 | "version": "0.24.2", 222 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", 223 | "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", 224 | "cpu": [ 225 | "arm64" 226 | ], 227 | "dev": true, 228 | "license": "MIT", 229 | "optional": true, 230 | "os": [ 231 | "darwin" 232 | ], 233 | "engines": { 234 | "node": ">=18" 235 | } 236 | }, 237 | "node_modules/@esbuild/darwin-x64": { 238 | "version": "0.24.2", 239 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", 240 | "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", 241 | "cpu": [ 242 | "x64" 243 | ], 244 | "dev": true, 245 | "license": "MIT", 246 | "optional": true, 247 | "os": [ 248 | "darwin" 249 | ], 250 | "engines": { 251 | "node": ">=18" 252 | } 253 | }, 254 | "node_modules/@esbuild/freebsd-arm64": { 255 | "version": "0.24.2", 256 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", 257 | "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", 258 | "cpu": [ 259 | "arm64" 260 | ], 261 | "dev": true, 262 | "license": "MIT", 263 | "optional": true, 264 | "os": [ 265 | "freebsd" 266 | ], 267 | "engines": { 268 | "node": ">=18" 269 | } 270 | }, 271 | "node_modules/@esbuild/freebsd-x64": { 272 | "version": "0.24.2", 273 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", 274 | "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", 275 | "cpu": [ 276 | "x64" 277 | ], 278 | "dev": true, 279 | "license": "MIT", 280 | "optional": true, 281 | "os": [ 282 | "freebsd" 283 | ], 284 | "engines": { 285 | "node": ">=18" 286 | } 287 | }, 288 | "node_modules/@esbuild/linux-arm": { 289 | "version": "0.24.2", 290 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", 291 | "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", 292 | "cpu": [ 293 | "arm" 294 | ], 295 | "dev": true, 296 | "license": "MIT", 297 | "optional": true, 298 | "os": [ 299 | "linux" 300 | ], 301 | "engines": { 302 | "node": ">=18" 303 | } 304 | }, 305 | "node_modules/@esbuild/linux-arm64": { 306 | "version": "0.24.2", 307 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", 308 | "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", 309 | "cpu": [ 310 | "arm64" 311 | ], 312 | "dev": true, 313 | "license": "MIT", 314 | "optional": true, 315 | "os": [ 316 | "linux" 317 | ], 318 | "engines": { 319 | "node": ">=18" 320 | } 321 | }, 322 | "node_modules/@esbuild/linux-ia32": { 323 | "version": "0.24.2", 324 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", 325 | "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", 326 | "cpu": [ 327 | "ia32" 328 | ], 329 | "dev": true, 330 | "license": "MIT", 331 | "optional": true, 332 | "os": [ 333 | "linux" 334 | ], 335 | "engines": { 336 | "node": ">=18" 337 | } 338 | }, 339 | "node_modules/@esbuild/linux-loong64": { 340 | "version": "0.24.2", 341 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", 342 | "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", 343 | "cpu": [ 344 | "loong64" 345 | ], 346 | "dev": true, 347 | "license": "MIT", 348 | "optional": true, 349 | "os": [ 350 | "linux" 351 | ], 352 | "engines": { 353 | "node": ">=18" 354 | } 355 | }, 356 | "node_modules/@esbuild/linux-mips64el": { 357 | "version": "0.24.2", 358 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", 359 | "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", 360 | "cpu": [ 361 | "mips64el" 362 | ], 363 | "dev": true, 364 | "license": "MIT", 365 | "optional": true, 366 | "os": [ 367 | "linux" 368 | ], 369 | "engines": { 370 | "node": ">=18" 371 | } 372 | }, 373 | "node_modules/@esbuild/linux-ppc64": { 374 | "version": "0.24.2", 375 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", 376 | "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", 377 | "cpu": [ 378 | "ppc64" 379 | ], 380 | "dev": true, 381 | "license": "MIT", 382 | "optional": true, 383 | "os": [ 384 | "linux" 385 | ], 386 | "engines": { 387 | "node": ">=18" 388 | } 389 | }, 390 | "node_modules/@esbuild/linux-riscv64": { 391 | "version": "0.24.2", 392 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", 393 | "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", 394 | "cpu": [ 395 | "riscv64" 396 | ], 397 | "dev": true, 398 | "license": "MIT", 399 | "optional": true, 400 | "os": [ 401 | "linux" 402 | ], 403 | "engines": { 404 | "node": ">=18" 405 | } 406 | }, 407 | "node_modules/@esbuild/linux-s390x": { 408 | "version": "0.24.2", 409 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", 410 | "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", 411 | "cpu": [ 412 | "s390x" 413 | ], 414 | "dev": true, 415 | "license": "MIT", 416 | "optional": true, 417 | "os": [ 418 | "linux" 419 | ], 420 | "engines": { 421 | "node": ">=18" 422 | } 423 | }, 424 | "node_modules/@esbuild/linux-x64": { 425 | "version": "0.24.2", 426 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", 427 | "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", 428 | "cpu": [ 429 | "x64" 430 | ], 431 | "dev": true, 432 | "license": "MIT", 433 | "optional": true, 434 | "os": [ 435 | "linux" 436 | ], 437 | "engines": { 438 | "node": ">=18" 439 | } 440 | }, 441 | "node_modules/@esbuild/netbsd-arm64": { 442 | "version": "0.24.2", 443 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", 444 | "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", 445 | "cpu": [ 446 | "arm64" 447 | ], 448 | "dev": true, 449 | "license": "MIT", 450 | "optional": true, 451 | "os": [ 452 | "netbsd" 453 | ], 454 | "engines": { 455 | "node": ">=18" 456 | } 457 | }, 458 | "node_modules/@esbuild/netbsd-x64": { 459 | "version": "0.24.2", 460 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", 461 | "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", 462 | "cpu": [ 463 | "x64" 464 | ], 465 | "dev": true, 466 | "license": "MIT", 467 | "optional": true, 468 | "os": [ 469 | "netbsd" 470 | ], 471 | "engines": { 472 | "node": ">=18" 473 | } 474 | }, 475 | "node_modules/@esbuild/openbsd-arm64": { 476 | "version": "0.24.2", 477 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", 478 | "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", 479 | "cpu": [ 480 | "arm64" 481 | ], 482 | "dev": true, 483 | "license": "MIT", 484 | "optional": true, 485 | "os": [ 486 | "openbsd" 487 | ], 488 | "engines": { 489 | "node": ">=18" 490 | } 491 | }, 492 | "node_modules/@esbuild/openbsd-x64": { 493 | "version": "0.24.2", 494 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", 495 | "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", 496 | "cpu": [ 497 | "x64" 498 | ], 499 | "dev": true, 500 | "license": "MIT", 501 | "optional": true, 502 | "os": [ 503 | "openbsd" 504 | ], 505 | "engines": { 506 | "node": ">=18" 507 | } 508 | }, 509 | "node_modules/@esbuild/sunos-x64": { 510 | "version": "0.24.2", 511 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", 512 | "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", 513 | "cpu": [ 514 | "x64" 515 | ], 516 | "dev": true, 517 | "license": "MIT", 518 | "optional": true, 519 | "os": [ 520 | "sunos" 521 | ], 522 | "engines": { 523 | "node": ">=18" 524 | } 525 | }, 526 | "node_modules/@esbuild/win32-arm64": { 527 | "version": "0.24.2", 528 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", 529 | "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", 530 | "cpu": [ 531 | "arm64" 532 | ], 533 | "dev": true, 534 | "license": "MIT", 535 | "optional": true, 536 | "os": [ 537 | "win32" 538 | ], 539 | "engines": { 540 | "node": ">=18" 541 | } 542 | }, 543 | "node_modules/@esbuild/win32-ia32": { 544 | "version": "0.24.2", 545 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", 546 | "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", 547 | "cpu": [ 548 | "ia32" 549 | ], 550 | "dev": true, 551 | "license": "MIT", 552 | "optional": true, 553 | "os": [ 554 | "win32" 555 | ], 556 | "engines": { 557 | "node": ">=18" 558 | } 559 | }, 560 | "node_modules/@esbuild/win32-x64": { 561 | "version": "0.24.2", 562 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", 563 | "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", 564 | "cpu": [ 565 | "x64" 566 | ], 567 | "dev": true, 568 | "license": "MIT", 569 | "optional": true, 570 | "os": [ 571 | "win32" 572 | ], 573 | "engines": { 574 | "node": ">=18" 575 | } 576 | }, 577 | "node_modules/@jridgewell/sourcemap-codec": { 578 | "version": "1.5.0", 579 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", 580 | "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", 581 | "dev": true, 582 | "license": "MIT" 583 | }, 584 | "node_modules/@nodelib/fs.scandir": { 585 | "version": "2.1.5", 586 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 587 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 588 | "dev": true, 589 | "license": "MIT", 590 | "dependencies": { 591 | "@nodelib/fs.stat": "2.0.5", 592 | "run-parallel": "^1.1.9" 593 | }, 594 | "engines": { 595 | "node": ">= 8" 596 | } 597 | }, 598 | "node_modules/@nodelib/fs.stat": { 599 | "version": "2.0.5", 600 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 601 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 602 | "dev": true, 603 | "license": "MIT", 604 | "engines": { 605 | "node": ">= 8" 606 | } 607 | }, 608 | "node_modules/@nodelib/fs.walk": { 609 | "version": "1.2.8", 610 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 611 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 612 | "dev": true, 613 | "license": "MIT", 614 | "dependencies": { 615 | "@nodelib/fs.scandir": "2.1.5", 616 | "fastq": "^1.6.0" 617 | }, 618 | "engines": { 619 | "node": ">= 8" 620 | } 621 | }, 622 | "node_modules/@rollup/rollup-android-arm-eabi": { 623 | "version": "4.34.8", 624 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz", 625 | "integrity": "sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==", 626 | "cpu": [ 627 | "arm" 628 | ], 629 | "dev": true, 630 | "license": "MIT", 631 | "optional": true, 632 | "os": [ 633 | "android" 634 | ] 635 | }, 636 | "node_modules/@rollup/rollup-android-arm64": { 637 | "version": "4.34.8", 638 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz", 639 | "integrity": "sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==", 640 | "cpu": [ 641 | "arm64" 642 | ], 643 | "dev": true, 644 | "license": "MIT", 645 | "optional": true, 646 | "os": [ 647 | "android" 648 | ] 649 | }, 650 | "node_modules/@rollup/rollup-darwin-arm64": { 651 | "version": "4.34.8", 652 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz", 653 | "integrity": "sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==", 654 | "cpu": [ 655 | "arm64" 656 | ], 657 | "dev": true, 658 | "license": "MIT", 659 | "optional": true, 660 | "os": [ 661 | "darwin" 662 | ] 663 | }, 664 | "node_modules/@rollup/rollup-darwin-x64": { 665 | "version": "4.34.8", 666 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz", 667 | "integrity": "sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==", 668 | "cpu": [ 669 | "x64" 670 | ], 671 | "dev": true, 672 | "license": "MIT", 673 | "optional": true, 674 | "os": [ 675 | "darwin" 676 | ] 677 | }, 678 | "node_modules/@rollup/rollup-freebsd-arm64": { 679 | "version": "4.34.8", 680 | "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz", 681 | "integrity": "sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==", 682 | "cpu": [ 683 | "arm64" 684 | ], 685 | "dev": true, 686 | "license": "MIT", 687 | "optional": true, 688 | "os": [ 689 | "freebsd" 690 | ] 691 | }, 692 | "node_modules/@rollup/rollup-freebsd-x64": { 693 | "version": "4.34.8", 694 | "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz", 695 | "integrity": "sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==", 696 | "cpu": [ 697 | "x64" 698 | ], 699 | "dev": true, 700 | "license": "MIT", 701 | "optional": true, 702 | "os": [ 703 | "freebsd" 704 | ] 705 | }, 706 | "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 707 | "version": "4.34.8", 708 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz", 709 | "integrity": "sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==", 710 | "cpu": [ 711 | "arm" 712 | ], 713 | "dev": true, 714 | "license": "MIT", 715 | "optional": true, 716 | "os": [ 717 | "linux" 718 | ] 719 | }, 720 | "node_modules/@rollup/rollup-linux-arm-musleabihf": { 721 | "version": "4.34.8", 722 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz", 723 | "integrity": "sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==", 724 | "cpu": [ 725 | "arm" 726 | ], 727 | "dev": true, 728 | "license": "MIT", 729 | "optional": true, 730 | "os": [ 731 | "linux" 732 | ] 733 | }, 734 | "node_modules/@rollup/rollup-linux-arm64-gnu": { 735 | "version": "4.34.8", 736 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz", 737 | "integrity": "sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==", 738 | "cpu": [ 739 | "arm64" 740 | ], 741 | "dev": true, 742 | "license": "MIT", 743 | "optional": true, 744 | "os": [ 745 | "linux" 746 | ] 747 | }, 748 | "node_modules/@rollup/rollup-linux-arm64-musl": { 749 | "version": "4.34.8", 750 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz", 751 | "integrity": "sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==", 752 | "cpu": [ 753 | "arm64" 754 | ], 755 | "dev": true, 756 | "license": "MIT", 757 | "optional": true, 758 | "os": [ 759 | "linux" 760 | ] 761 | }, 762 | "node_modules/@rollup/rollup-linux-loongarch64-gnu": { 763 | "version": "4.34.8", 764 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.8.tgz", 765 | "integrity": "sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==", 766 | "cpu": [ 767 | "loong64" 768 | ], 769 | "dev": true, 770 | "license": "MIT", 771 | "optional": true, 772 | "os": [ 773 | "linux" 774 | ] 775 | }, 776 | "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { 777 | "version": "4.34.8", 778 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.8.tgz", 779 | "integrity": "sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==", 780 | "cpu": [ 781 | "ppc64" 782 | ], 783 | "dev": true, 784 | "license": "MIT", 785 | "optional": true, 786 | "os": [ 787 | "linux" 788 | ] 789 | }, 790 | "node_modules/@rollup/rollup-linux-riscv64-gnu": { 791 | "version": "4.34.8", 792 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz", 793 | "integrity": "sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==", 794 | "cpu": [ 795 | "riscv64" 796 | ], 797 | "dev": true, 798 | "license": "MIT", 799 | "optional": true, 800 | "os": [ 801 | "linux" 802 | ] 803 | }, 804 | "node_modules/@rollup/rollup-linux-s390x-gnu": { 805 | "version": "4.34.8", 806 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz", 807 | "integrity": "sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==", 808 | "cpu": [ 809 | "s390x" 810 | ], 811 | "dev": true, 812 | "license": "MIT", 813 | "optional": true, 814 | "os": [ 815 | "linux" 816 | ] 817 | }, 818 | "node_modules/@rollup/rollup-linux-x64-gnu": { 819 | "version": "4.34.8", 820 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz", 821 | "integrity": "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==", 822 | "cpu": [ 823 | "x64" 824 | ], 825 | "dev": true, 826 | "license": "MIT", 827 | "optional": true, 828 | "os": [ 829 | "linux" 830 | ] 831 | }, 832 | "node_modules/@rollup/rollup-linux-x64-musl": { 833 | "version": "4.34.8", 834 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz", 835 | "integrity": "sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==", 836 | "cpu": [ 837 | "x64" 838 | ], 839 | "dev": true, 840 | "license": "MIT", 841 | "optional": true, 842 | "os": [ 843 | "linux" 844 | ] 845 | }, 846 | "node_modules/@rollup/rollup-win32-arm64-msvc": { 847 | "version": "4.34.8", 848 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz", 849 | "integrity": "sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==", 850 | "cpu": [ 851 | "arm64" 852 | ], 853 | "dev": true, 854 | "license": "MIT", 855 | "optional": true, 856 | "os": [ 857 | "win32" 858 | ] 859 | }, 860 | "node_modules/@rollup/rollup-win32-ia32-msvc": { 861 | "version": "4.34.8", 862 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz", 863 | "integrity": "sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==", 864 | "cpu": [ 865 | "ia32" 866 | ], 867 | "dev": true, 868 | "license": "MIT", 869 | "optional": true, 870 | "os": [ 871 | "win32" 872 | ] 873 | }, 874 | "node_modules/@rollup/rollup-win32-x64-msvc": { 875 | "version": "4.34.8", 876 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz", 877 | "integrity": "sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==", 878 | "cpu": [ 879 | "x64" 880 | ], 881 | "dev": true, 882 | "license": "MIT", 883 | "optional": true, 884 | "os": [ 885 | "win32" 886 | ] 887 | }, 888 | "node_modules/@total-typescript/exercise-cli": { 889 | "version": "0.11.0", 890 | "resolved": "https://registry.npmjs.org/@total-typescript/exercise-cli/-/exercise-cli-0.11.0.tgz", 891 | "integrity": "sha512-VTRT1UTedPEburo5uQZLDchnbUAciOKsnO89y7DAKJS3/NMAObi6gr1/SNlCcEmCRa/Rya2mLG+iYBYhnmYsYA==", 892 | "dev": true, 893 | "license": "ISC", 894 | "dependencies": { 895 | "chokidar": "^3.5.3", 896 | "colors": "^1.4.0", 897 | "commander": "^10.0.1", 898 | "fast-glob": "^3.2.12", 899 | "jsonc-parser": "^3.2.0", 900 | "prompts": "^2.4.2" 901 | }, 902 | "bin": { 903 | "tt-cli": "dist/bin.js" 904 | }, 905 | "peerDependencies": { 906 | "typescript": "*", 907 | "vitest": "*" 908 | } 909 | }, 910 | "node_modules/@types/estree": { 911 | "version": "1.0.6", 912 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", 913 | "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", 914 | "dev": true, 915 | "license": "MIT" 916 | }, 917 | "node_modules/@types/node": { 918 | "version": "18.19.76", 919 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.76.tgz", 920 | "integrity": "sha512-yvR7Q9LdPz2vGpmpJX5LolrgRdWvB67MJKDPSgIIzpFbaf9a1j/f5DnLp5VDyHGMR0QZHlTr1afsD87QCXFHKw==", 921 | "dev": true, 922 | "license": "MIT", 923 | "dependencies": { 924 | "undici-types": "~5.26.4" 925 | } 926 | }, 927 | "node_modules/@vitest/expect": { 928 | "version": "3.0.5", 929 | "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.5.tgz", 930 | "integrity": "sha512-nNIOqupgZ4v5jWuQx2DSlHLEs7Q4Oh/7AYwNyE+k0UQzG7tSmjPXShUikn1mpNGzYEN2jJbTvLejwShMitovBA==", 931 | "dev": true, 932 | "license": "MIT", 933 | "dependencies": { 934 | "@vitest/spy": "3.0.5", 935 | "@vitest/utils": "3.0.5", 936 | "chai": "^5.1.2", 937 | "tinyrainbow": "^2.0.0" 938 | }, 939 | "funding": { 940 | "url": "https://opencollective.com/vitest" 941 | } 942 | }, 943 | "node_modules/@vitest/mocker": { 944 | "version": "3.0.5", 945 | "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.5.tgz", 946 | "integrity": "sha512-CLPNBFBIE7x6aEGbIjaQAX03ZZlBMaWwAjBdMkIf/cAn6xzLTiM3zYqO/WAbieEjsAZir6tO71mzeHZoodThvw==", 947 | "dev": true, 948 | "license": "MIT", 949 | "dependencies": { 950 | "@vitest/spy": "3.0.5", 951 | "estree-walker": "^3.0.3", 952 | "magic-string": "^0.30.17" 953 | }, 954 | "funding": { 955 | "url": "https://opencollective.com/vitest" 956 | }, 957 | "peerDependencies": { 958 | "msw": "^2.4.9", 959 | "vite": "^5.0.0 || ^6.0.0" 960 | }, 961 | "peerDependenciesMeta": { 962 | "msw": { 963 | "optional": true 964 | }, 965 | "vite": { 966 | "optional": true 967 | } 968 | } 969 | }, 970 | "node_modules/@vitest/pretty-format": { 971 | "version": "3.0.5", 972 | "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.5.tgz", 973 | "integrity": "sha512-CjUtdmpOcm4RVtB+up8r2vVDLR16Mgm/bYdkGFe3Yj/scRfCpbSi2W/BDSDcFK7ohw8UXvjMbOp9H4fByd/cOA==", 974 | "dev": true, 975 | "license": "MIT", 976 | "dependencies": { 977 | "tinyrainbow": "^2.0.0" 978 | }, 979 | "funding": { 980 | "url": "https://opencollective.com/vitest" 981 | } 982 | }, 983 | "node_modules/@vitest/runner": { 984 | "version": "3.0.5", 985 | "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.5.tgz", 986 | "integrity": "sha512-BAiZFityFexZQi2yN4OX3OkJC6scwRo8EhRB0Z5HIGGgd2q+Nq29LgHU/+ovCtd0fOfXj5ZI6pwdlUmC5bpi8A==", 987 | "dev": true, 988 | "license": "MIT", 989 | "dependencies": { 990 | "@vitest/utils": "3.0.5", 991 | "pathe": "^2.0.2" 992 | }, 993 | "funding": { 994 | "url": "https://opencollective.com/vitest" 995 | } 996 | }, 997 | "node_modules/@vitest/snapshot": { 998 | "version": "3.0.5", 999 | "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.5.tgz", 1000 | "integrity": "sha512-GJPZYcd7v8QNUJ7vRvLDmRwl+a1fGg4T/54lZXe+UOGy47F9yUfE18hRCtXL5aHN/AONu29NGzIXSVFh9K0feA==", 1001 | "dev": true, 1002 | "license": "MIT", 1003 | "dependencies": { 1004 | "@vitest/pretty-format": "3.0.5", 1005 | "magic-string": "^0.30.17", 1006 | "pathe": "^2.0.2" 1007 | }, 1008 | "funding": { 1009 | "url": "https://opencollective.com/vitest" 1010 | } 1011 | }, 1012 | "node_modules/@vitest/spy": { 1013 | "version": "3.0.5", 1014 | "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.5.tgz", 1015 | "integrity": "sha512-5fOzHj0WbUNqPK6blI/8VzZdkBlQLnT25knX0r4dbZI9qoZDf3qAdjoMmDcLG5A83W6oUUFJgUd0EYBc2P5xqg==", 1016 | "dev": true, 1017 | "license": "MIT", 1018 | "dependencies": { 1019 | "tinyspy": "^3.0.2" 1020 | }, 1021 | "funding": { 1022 | "url": "https://opencollective.com/vitest" 1023 | } 1024 | }, 1025 | "node_modules/@vitest/utils": { 1026 | "version": "3.0.5", 1027 | "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.5.tgz", 1028 | "integrity": "sha512-N9AX0NUoUtVwKwy21JtwzaqR5L5R5A99GAbrHfCCXK1lp593i/3AZAXhSP43wRQuxYsflrdzEfXZFo1reR1Nkg==", 1029 | "dev": true, 1030 | "license": "MIT", 1031 | "dependencies": { 1032 | "@vitest/pretty-format": "3.0.5", 1033 | "loupe": "^3.1.2", 1034 | "tinyrainbow": "^2.0.0" 1035 | }, 1036 | "funding": { 1037 | "url": "https://opencollective.com/vitest" 1038 | } 1039 | }, 1040 | "node_modules/agent-base": { 1041 | "version": "7.1.3", 1042 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", 1043 | "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", 1044 | "dev": true, 1045 | "license": "MIT", 1046 | "engines": { 1047 | "node": ">= 14" 1048 | } 1049 | }, 1050 | "node_modules/anymatch": { 1051 | "version": "3.1.3", 1052 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 1053 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 1054 | "dev": true, 1055 | "license": "ISC", 1056 | "dependencies": { 1057 | "normalize-path": "^3.0.0", 1058 | "picomatch": "^2.0.4" 1059 | }, 1060 | "engines": { 1061 | "node": ">= 8" 1062 | } 1063 | }, 1064 | "node_modules/assertion-error": { 1065 | "version": "2.0.1", 1066 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", 1067 | "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", 1068 | "dev": true, 1069 | "license": "MIT", 1070 | "engines": { 1071 | "node": ">=12" 1072 | } 1073 | }, 1074 | "node_modules/asynckit": { 1075 | "version": "0.4.0", 1076 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 1077 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", 1078 | "dev": true, 1079 | "license": "MIT" 1080 | }, 1081 | "node_modules/binary-extensions": { 1082 | "version": "2.3.0", 1083 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", 1084 | "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", 1085 | "dev": true, 1086 | "license": "MIT", 1087 | "engines": { 1088 | "node": ">=8" 1089 | }, 1090 | "funding": { 1091 | "url": "https://github.com/sponsors/sindresorhus" 1092 | } 1093 | }, 1094 | "node_modules/braces": { 1095 | "version": "3.0.3", 1096 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", 1097 | "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", 1098 | "dev": true, 1099 | "license": "MIT", 1100 | "dependencies": { 1101 | "fill-range": "^7.1.1" 1102 | }, 1103 | "engines": { 1104 | "node": ">=8" 1105 | } 1106 | }, 1107 | "node_modules/cac": { 1108 | "version": "6.7.14", 1109 | "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", 1110 | "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", 1111 | "dev": true, 1112 | "license": "MIT", 1113 | "engines": { 1114 | "node": ">=8" 1115 | } 1116 | }, 1117 | "node_modules/call-bind-apply-helpers": { 1118 | "version": "1.0.2", 1119 | "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", 1120 | "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", 1121 | "dev": true, 1122 | "license": "MIT", 1123 | "dependencies": { 1124 | "es-errors": "^1.3.0", 1125 | "function-bind": "^1.1.2" 1126 | }, 1127 | "engines": { 1128 | "node": ">= 0.4" 1129 | } 1130 | }, 1131 | "node_modules/chai": { 1132 | "version": "5.2.0", 1133 | "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", 1134 | "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", 1135 | "dev": true, 1136 | "license": "MIT", 1137 | "dependencies": { 1138 | "assertion-error": "^2.0.1", 1139 | "check-error": "^2.1.1", 1140 | "deep-eql": "^5.0.1", 1141 | "loupe": "^3.1.0", 1142 | "pathval": "^2.0.0" 1143 | }, 1144 | "engines": { 1145 | "node": ">=12" 1146 | } 1147 | }, 1148 | "node_modules/check-error": { 1149 | "version": "2.1.1", 1150 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", 1151 | "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", 1152 | "dev": true, 1153 | "license": "MIT", 1154 | "engines": { 1155 | "node": ">= 16" 1156 | } 1157 | }, 1158 | "node_modules/chokidar": { 1159 | "version": "3.6.0", 1160 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", 1161 | "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", 1162 | "dev": true, 1163 | "license": "MIT", 1164 | "dependencies": { 1165 | "anymatch": "~3.1.2", 1166 | "braces": "~3.0.2", 1167 | "glob-parent": "~5.1.2", 1168 | "is-binary-path": "~2.1.0", 1169 | "is-glob": "~4.0.1", 1170 | "normalize-path": "~3.0.0", 1171 | "readdirp": "~3.6.0" 1172 | }, 1173 | "engines": { 1174 | "node": ">= 8.10.0" 1175 | }, 1176 | "funding": { 1177 | "url": "https://paulmillr.com/funding/" 1178 | }, 1179 | "optionalDependencies": { 1180 | "fsevents": "~2.3.2" 1181 | } 1182 | }, 1183 | "node_modules/colors": { 1184 | "version": "1.4.0", 1185 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", 1186 | "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", 1187 | "dev": true, 1188 | "license": "MIT", 1189 | "engines": { 1190 | "node": ">=0.1.90" 1191 | } 1192 | }, 1193 | "node_modules/combined-stream": { 1194 | "version": "1.0.8", 1195 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 1196 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 1197 | "dev": true, 1198 | "license": "MIT", 1199 | "dependencies": { 1200 | "delayed-stream": "~1.0.0" 1201 | }, 1202 | "engines": { 1203 | "node": ">= 0.8" 1204 | } 1205 | }, 1206 | "node_modules/commander": { 1207 | "version": "10.0.1", 1208 | "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", 1209 | "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", 1210 | "dev": true, 1211 | "license": "MIT", 1212 | "engines": { 1213 | "node": ">=14" 1214 | } 1215 | }, 1216 | "node_modules/cssstyle": { 1217 | "version": "4.2.1", 1218 | "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.2.1.tgz", 1219 | "integrity": "sha512-9+vem03dMXG7gDmZ62uqmRiMRNtinIZ9ZyuF6BdxzfOD+FdN5hretzynkn0ReS2DO2GSw76RWHs0UmJPI2zUjw==", 1220 | "dev": true, 1221 | "license": "MIT", 1222 | "dependencies": { 1223 | "@asamuzakjp/css-color": "^2.8.2", 1224 | "rrweb-cssom": "^0.8.0" 1225 | }, 1226 | "engines": { 1227 | "node": ">=18" 1228 | } 1229 | }, 1230 | "node_modules/cssstyle/node_modules/rrweb-cssom": { 1231 | "version": "0.8.0", 1232 | "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", 1233 | "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", 1234 | "dev": true, 1235 | "license": "MIT" 1236 | }, 1237 | "node_modules/data-urls": { 1238 | "version": "5.0.0", 1239 | "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", 1240 | "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", 1241 | "dev": true, 1242 | "license": "MIT", 1243 | "dependencies": { 1244 | "whatwg-mimetype": "^4.0.0", 1245 | "whatwg-url": "^14.0.0" 1246 | }, 1247 | "engines": { 1248 | "node": ">=18" 1249 | } 1250 | }, 1251 | "node_modules/debug": { 1252 | "version": "4.4.0", 1253 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 1254 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 1255 | "dev": true, 1256 | "license": "MIT", 1257 | "dependencies": { 1258 | "ms": "^2.1.3" 1259 | }, 1260 | "engines": { 1261 | "node": ">=6.0" 1262 | }, 1263 | "peerDependenciesMeta": { 1264 | "supports-color": { 1265 | "optional": true 1266 | } 1267 | } 1268 | }, 1269 | "node_modules/decimal.js": { 1270 | "version": "10.5.0", 1271 | "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", 1272 | "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", 1273 | "dev": true, 1274 | "license": "MIT" 1275 | }, 1276 | "node_modules/deep-eql": { 1277 | "version": "5.0.2", 1278 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", 1279 | "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", 1280 | "dev": true, 1281 | "license": "MIT", 1282 | "engines": { 1283 | "node": ">=6" 1284 | } 1285 | }, 1286 | "node_modules/delayed-stream": { 1287 | "version": "1.0.0", 1288 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 1289 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", 1290 | "dev": true, 1291 | "license": "MIT", 1292 | "engines": { 1293 | "node": ">=0.4.0" 1294 | } 1295 | }, 1296 | "node_modules/dunder-proto": { 1297 | "version": "1.0.1", 1298 | "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", 1299 | "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", 1300 | "dev": true, 1301 | "license": "MIT", 1302 | "dependencies": { 1303 | "call-bind-apply-helpers": "^1.0.1", 1304 | "es-errors": "^1.3.0", 1305 | "gopd": "^1.2.0" 1306 | }, 1307 | "engines": { 1308 | "node": ">= 0.4" 1309 | } 1310 | }, 1311 | "node_modules/entities": { 1312 | "version": "4.5.0", 1313 | "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", 1314 | "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", 1315 | "dev": true, 1316 | "license": "BSD-2-Clause", 1317 | "engines": { 1318 | "node": ">=0.12" 1319 | }, 1320 | "funding": { 1321 | "url": "https://github.com/fb55/entities?sponsor=1" 1322 | } 1323 | }, 1324 | "node_modules/es-define-property": { 1325 | "version": "1.0.1", 1326 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", 1327 | "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", 1328 | "dev": true, 1329 | "license": "MIT", 1330 | "engines": { 1331 | "node": ">= 0.4" 1332 | } 1333 | }, 1334 | "node_modules/es-errors": { 1335 | "version": "1.3.0", 1336 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 1337 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 1338 | "dev": true, 1339 | "license": "MIT", 1340 | "engines": { 1341 | "node": ">= 0.4" 1342 | } 1343 | }, 1344 | "node_modules/es-module-lexer": { 1345 | "version": "1.6.0", 1346 | "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", 1347 | "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", 1348 | "dev": true, 1349 | "license": "MIT" 1350 | }, 1351 | "node_modules/es-object-atoms": { 1352 | "version": "1.1.1", 1353 | "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", 1354 | "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", 1355 | "dev": true, 1356 | "license": "MIT", 1357 | "dependencies": { 1358 | "es-errors": "^1.3.0" 1359 | }, 1360 | "engines": { 1361 | "node": ">= 0.4" 1362 | } 1363 | }, 1364 | "node_modules/es-set-tostringtag": { 1365 | "version": "2.1.0", 1366 | "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", 1367 | "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", 1368 | "dev": true, 1369 | "license": "MIT", 1370 | "dependencies": { 1371 | "es-errors": "^1.3.0", 1372 | "get-intrinsic": "^1.2.6", 1373 | "has-tostringtag": "^1.0.2", 1374 | "hasown": "^2.0.2" 1375 | }, 1376 | "engines": { 1377 | "node": ">= 0.4" 1378 | } 1379 | }, 1380 | "node_modules/esbuild": { 1381 | "version": "0.24.2", 1382 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", 1383 | "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", 1384 | "dev": true, 1385 | "hasInstallScript": true, 1386 | "license": "MIT", 1387 | "bin": { 1388 | "esbuild": "bin/esbuild" 1389 | }, 1390 | "engines": { 1391 | "node": ">=18" 1392 | }, 1393 | "optionalDependencies": { 1394 | "@esbuild/aix-ppc64": "0.24.2", 1395 | "@esbuild/android-arm": "0.24.2", 1396 | "@esbuild/android-arm64": "0.24.2", 1397 | "@esbuild/android-x64": "0.24.2", 1398 | "@esbuild/darwin-arm64": "0.24.2", 1399 | "@esbuild/darwin-x64": "0.24.2", 1400 | "@esbuild/freebsd-arm64": "0.24.2", 1401 | "@esbuild/freebsd-x64": "0.24.2", 1402 | "@esbuild/linux-arm": "0.24.2", 1403 | "@esbuild/linux-arm64": "0.24.2", 1404 | "@esbuild/linux-ia32": "0.24.2", 1405 | "@esbuild/linux-loong64": "0.24.2", 1406 | "@esbuild/linux-mips64el": "0.24.2", 1407 | "@esbuild/linux-ppc64": "0.24.2", 1408 | "@esbuild/linux-riscv64": "0.24.2", 1409 | "@esbuild/linux-s390x": "0.24.2", 1410 | "@esbuild/linux-x64": "0.24.2", 1411 | "@esbuild/netbsd-arm64": "0.24.2", 1412 | "@esbuild/netbsd-x64": "0.24.2", 1413 | "@esbuild/openbsd-arm64": "0.24.2", 1414 | "@esbuild/openbsd-x64": "0.24.2", 1415 | "@esbuild/sunos-x64": "0.24.2", 1416 | "@esbuild/win32-arm64": "0.24.2", 1417 | "@esbuild/win32-ia32": "0.24.2", 1418 | "@esbuild/win32-x64": "0.24.2" 1419 | } 1420 | }, 1421 | "node_modules/estree-walker": { 1422 | "version": "3.0.3", 1423 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", 1424 | "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", 1425 | "dev": true, 1426 | "license": "MIT", 1427 | "dependencies": { 1428 | "@types/estree": "^1.0.0" 1429 | } 1430 | }, 1431 | "node_modules/expect-type": { 1432 | "version": "1.1.0", 1433 | "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.1.0.tgz", 1434 | "integrity": "sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==", 1435 | "dev": true, 1436 | "license": "Apache-2.0", 1437 | "engines": { 1438 | "node": ">=12.0.0" 1439 | } 1440 | }, 1441 | "node_modules/fast-glob": { 1442 | "version": "3.3.3", 1443 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", 1444 | "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", 1445 | "dev": true, 1446 | "license": "MIT", 1447 | "dependencies": { 1448 | "@nodelib/fs.stat": "^2.0.2", 1449 | "@nodelib/fs.walk": "^1.2.3", 1450 | "glob-parent": "^5.1.2", 1451 | "merge2": "^1.3.0", 1452 | "micromatch": "^4.0.8" 1453 | }, 1454 | "engines": { 1455 | "node": ">=8.6.0" 1456 | } 1457 | }, 1458 | "node_modules/fastq": { 1459 | "version": "1.19.0", 1460 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz", 1461 | "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==", 1462 | "dev": true, 1463 | "license": "ISC", 1464 | "dependencies": { 1465 | "reusify": "^1.0.4" 1466 | } 1467 | }, 1468 | "node_modules/fill-range": { 1469 | "version": "7.1.1", 1470 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", 1471 | "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", 1472 | "dev": true, 1473 | "license": "MIT", 1474 | "dependencies": { 1475 | "to-regex-range": "^5.0.1" 1476 | }, 1477 | "engines": { 1478 | "node": ">=8" 1479 | } 1480 | }, 1481 | "node_modules/form-data": { 1482 | "version": "4.0.2", 1483 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", 1484 | "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", 1485 | "dev": true, 1486 | "license": "MIT", 1487 | "dependencies": { 1488 | "asynckit": "^0.4.0", 1489 | "combined-stream": "^1.0.8", 1490 | "es-set-tostringtag": "^2.1.0", 1491 | "mime-types": "^2.1.12" 1492 | }, 1493 | "engines": { 1494 | "node": ">= 6" 1495 | } 1496 | }, 1497 | "node_modules/fsevents": { 1498 | "version": "2.3.3", 1499 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1500 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1501 | "dev": true, 1502 | "hasInstallScript": true, 1503 | "license": "MIT", 1504 | "optional": true, 1505 | "os": [ 1506 | "darwin" 1507 | ], 1508 | "engines": { 1509 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1510 | } 1511 | }, 1512 | "node_modules/function-bind": { 1513 | "version": "1.1.2", 1514 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 1515 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 1516 | "dev": true, 1517 | "license": "MIT", 1518 | "funding": { 1519 | "url": "https://github.com/sponsors/ljharb" 1520 | } 1521 | }, 1522 | "node_modules/get-intrinsic": { 1523 | "version": "1.2.7", 1524 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", 1525 | "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", 1526 | "dev": true, 1527 | "license": "MIT", 1528 | "dependencies": { 1529 | "call-bind-apply-helpers": "^1.0.1", 1530 | "es-define-property": "^1.0.1", 1531 | "es-errors": "^1.3.0", 1532 | "es-object-atoms": "^1.0.0", 1533 | "function-bind": "^1.1.2", 1534 | "get-proto": "^1.0.0", 1535 | "gopd": "^1.2.0", 1536 | "has-symbols": "^1.1.0", 1537 | "hasown": "^2.0.2", 1538 | "math-intrinsics": "^1.1.0" 1539 | }, 1540 | "engines": { 1541 | "node": ">= 0.4" 1542 | }, 1543 | "funding": { 1544 | "url": "https://github.com/sponsors/ljharb" 1545 | } 1546 | }, 1547 | "node_modules/get-proto": { 1548 | "version": "1.0.1", 1549 | "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", 1550 | "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", 1551 | "dev": true, 1552 | "license": "MIT", 1553 | "dependencies": { 1554 | "dunder-proto": "^1.0.1", 1555 | "es-object-atoms": "^1.0.0" 1556 | }, 1557 | "engines": { 1558 | "node": ">= 0.4" 1559 | } 1560 | }, 1561 | "node_modules/glob-parent": { 1562 | "version": "5.1.2", 1563 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 1564 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 1565 | "dev": true, 1566 | "license": "ISC", 1567 | "dependencies": { 1568 | "is-glob": "^4.0.1" 1569 | }, 1570 | "engines": { 1571 | "node": ">= 6" 1572 | } 1573 | }, 1574 | "node_modules/globrex": { 1575 | "version": "0.1.2", 1576 | "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", 1577 | "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", 1578 | "dev": true, 1579 | "license": "MIT" 1580 | }, 1581 | "node_modules/gopd": { 1582 | "version": "1.2.0", 1583 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", 1584 | "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", 1585 | "dev": true, 1586 | "license": "MIT", 1587 | "engines": { 1588 | "node": ">= 0.4" 1589 | }, 1590 | "funding": { 1591 | "url": "https://github.com/sponsors/ljharb" 1592 | } 1593 | }, 1594 | "node_modules/has-symbols": { 1595 | "version": "1.1.0", 1596 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", 1597 | "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", 1598 | "dev": true, 1599 | "license": "MIT", 1600 | "engines": { 1601 | "node": ">= 0.4" 1602 | }, 1603 | "funding": { 1604 | "url": "https://github.com/sponsors/ljharb" 1605 | } 1606 | }, 1607 | "node_modules/has-tostringtag": { 1608 | "version": "1.0.2", 1609 | "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", 1610 | "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", 1611 | "dev": true, 1612 | "license": "MIT", 1613 | "dependencies": { 1614 | "has-symbols": "^1.0.3" 1615 | }, 1616 | "engines": { 1617 | "node": ">= 0.4" 1618 | }, 1619 | "funding": { 1620 | "url": "https://github.com/sponsors/ljharb" 1621 | } 1622 | }, 1623 | "node_modules/hasown": { 1624 | "version": "2.0.2", 1625 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 1626 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 1627 | "dev": true, 1628 | "license": "MIT", 1629 | "dependencies": { 1630 | "function-bind": "^1.1.2" 1631 | }, 1632 | "engines": { 1633 | "node": ">= 0.4" 1634 | } 1635 | }, 1636 | "node_modules/html-encoding-sniffer": { 1637 | "version": "4.0.0", 1638 | "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", 1639 | "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", 1640 | "dev": true, 1641 | "license": "MIT", 1642 | "dependencies": { 1643 | "whatwg-encoding": "^3.1.1" 1644 | }, 1645 | "engines": { 1646 | "node": ">=18" 1647 | } 1648 | }, 1649 | "node_modules/http-proxy-agent": { 1650 | "version": "7.0.2", 1651 | "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", 1652 | "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", 1653 | "dev": true, 1654 | "license": "MIT", 1655 | "dependencies": { 1656 | "agent-base": "^7.1.0", 1657 | "debug": "^4.3.4" 1658 | }, 1659 | "engines": { 1660 | "node": ">= 14" 1661 | } 1662 | }, 1663 | "node_modules/https-proxy-agent": { 1664 | "version": "7.0.6", 1665 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", 1666 | "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", 1667 | "dev": true, 1668 | "license": "MIT", 1669 | "dependencies": { 1670 | "agent-base": "^7.1.2", 1671 | "debug": "4" 1672 | }, 1673 | "engines": { 1674 | "node": ">= 14" 1675 | } 1676 | }, 1677 | "node_modules/iconv-lite": { 1678 | "version": "0.6.3", 1679 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 1680 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 1681 | "dev": true, 1682 | "license": "MIT", 1683 | "dependencies": { 1684 | "safer-buffer": ">= 2.1.2 < 3.0.0" 1685 | }, 1686 | "engines": { 1687 | "node": ">=0.10.0" 1688 | } 1689 | }, 1690 | "node_modules/is-binary-path": { 1691 | "version": "2.1.0", 1692 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 1693 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 1694 | "dev": true, 1695 | "license": "MIT", 1696 | "dependencies": { 1697 | "binary-extensions": "^2.0.0" 1698 | }, 1699 | "engines": { 1700 | "node": ">=8" 1701 | } 1702 | }, 1703 | "node_modules/is-extglob": { 1704 | "version": "2.1.1", 1705 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1706 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 1707 | "dev": true, 1708 | "license": "MIT", 1709 | "engines": { 1710 | "node": ">=0.10.0" 1711 | } 1712 | }, 1713 | "node_modules/is-glob": { 1714 | "version": "4.0.3", 1715 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 1716 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 1717 | "dev": true, 1718 | "license": "MIT", 1719 | "dependencies": { 1720 | "is-extglob": "^2.1.1" 1721 | }, 1722 | "engines": { 1723 | "node": ">=0.10.0" 1724 | } 1725 | }, 1726 | "node_modules/is-number": { 1727 | "version": "7.0.0", 1728 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1729 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1730 | "dev": true, 1731 | "license": "MIT", 1732 | "engines": { 1733 | "node": ">=0.12.0" 1734 | } 1735 | }, 1736 | "node_modules/is-potential-custom-element-name": { 1737 | "version": "1.0.1", 1738 | "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", 1739 | "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", 1740 | "dev": true, 1741 | "license": "MIT" 1742 | }, 1743 | "node_modules/jsdom": { 1744 | "version": "25.0.1", 1745 | "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", 1746 | "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", 1747 | "dev": true, 1748 | "license": "MIT", 1749 | "dependencies": { 1750 | "cssstyle": "^4.1.0", 1751 | "data-urls": "^5.0.0", 1752 | "decimal.js": "^10.4.3", 1753 | "form-data": "^4.0.0", 1754 | "html-encoding-sniffer": "^4.0.0", 1755 | "http-proxy-agent": "^7.0.2", 1756 | "https-proxy-agent": "^7.0.5", 1757 | "is-potential-custom-element-name": "^1.0.1", 1758 | "nwsapi": "^2.2.12", 1759 | "parse5": "^7.1.2", 1760 | "rrweb-cssom": "^0.7.1", 1761 | "saxes": "^6.0.0", 1762 | "symbol-tree": "^3.2.4", 1763 | "tough-cookie": "^5.0.0", 1764 | "w3c-xmlserializer": "^5.0.0", 1765 | "webidl-conversions": "^7.0.0", 1766 | "whatwg-encoding": "^3.1.1", 1767 | "whatwg-mimetype": "^4.0.0", 1768 | "whatwg-url": "^14.0.0", 1769 | "ws": "^8.18.0", 1770 | "xml-name-validator": "^5.0.0" 1771 | }, 1772 | "engines": { 1773 | "node": ">=18" 1774 | }, 1775 | "peerDependencies": { 1776 | "canvas": "^2.11.2" 1777 | }, 1778 | "peerDependenciesMeta": { 1779 | "canvas": { 1780 | "optional": true 1781 | } 1782 | } 1783 | }, 1784 | "node_modules/jsonc-parser": { 1785 | "version": "3.3.1", 1786 | "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", 1787 | "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", 1788 | "dev": true, 1789 | "license": "MIT" 1790 | }, 1791 | "node_modules/kleur": { 1792 | "version": "3.0.3", 1793 | "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", 1794 | "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", 1795 | "dev": true, 1796 | "license": "MIT", 1797 | "engines": { 1798 | "node": ">=6" 1799 | } 1800 | }, 1801 | "node_modules/loupe": { 1802 | "version": "3.1.3", 1803 | "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", 1804 | "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", 1805 | "dev": true, 1806 | "license": "MIT" 1807 | }, 1808 | "node_modules/lru-cache": { 1809 | "version": "10.4.3", 1810 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", 1811 | "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", 1812 | "dev": true, 1813 | "license": "ISC" 1814 | }, 1815 | "node_modules/magic-string": { 1816 | "version": "0.30.17", 1817 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", 1818 | "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", 1819 | "dev": true, 1820 | "license": "MIT", 1821 | "dependencies": { 1822 | "@jridgewell/sourcemap-codec": "^1.5.0" 1823 | } 1824 | }, 1825 | "node_modules/math-intrinsics": { 1826 | "version": "1.1.0", 1827 | "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", 1828 | "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", 1829 | "dev": true, 1830 | "license": "MIT", 1831 | "engines": { 1832 | "node": ">= 0.4" 1833 | } 1834 | }, 1835 | "node_modules/merge2": { 1836 | "version": "1.4.1", 1837 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 1838 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 1839 | "dev": true, 1840 | "license": "MIT", 1841 | "engines": { 1842 | "node": ">= 8" 1843 | } 1844 | }, 1845 | "node_modules/micromatch": { 1846 | "version": "4.0.8", 1847 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", 1848 | "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", 1849 | "dev": true, 1850 | "license": "MIT", 1851 | "dependencies": { 1852 | "braces": "^3.0.3", 1853 | "picomatch": "^2.3.1" 1854 | }, 1855 | "engines": { 1856 | "node": ">=8.6" 1857 | } 1858 | }, 1859 | "node_modules/mime-db": { 1860 | "version": "1.52.0", 1861 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 1862 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 1863 | "dev": true, 1864 | "license": "MIT", 1865 | "engines": { 1866 | "node": ">= 0.6" 1867 | } 1868 | }, 1869 | "node_modules/mime-types": { 1870 | "version": "2.1.35", 1871 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 1872 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 1873 | "dev": true, 1874 | "license": "MIT", 1875 | "dependencies": { 1876 | "mime-db": "1.52.0" 1877 | }, 1878 | "engines": { 1879 | "node": ">= 0.6" 1880 | } 1881 | }, 1882 | "node_modules/ms": { 1883 | "version": "2.1.3", 1884 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1885 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1886 | "dev": true, 1887 | "license": "MIT" 1888 | }, 1889 | "node_modules/nanoid": { 1890 | "version": "3.3.8", 1891 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", 1892 | "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", 1893 | "dev": true, 1894 | "funding": [ 1895 | { 1896 | "type": "github", 1897 | "url": "https://github.com/sponsors/ai" 1898 | } 1899 | ], 1900 | "license": "MIT", 1901 | "bin": { 1902 | "nanoid": "bin/nanoid.cjs" 1903 | }, 1904 | "engines": { 1905 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 1906 | } 1907 | }, 1908 | "node_modules/normalize-path": { 1909 | "version": "3.0.0", 1910 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1911 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1912 | "dev": true, 1913 | "license": "MIT", 1914 | "engines": { 1915 | "node": ">=0.10.0" 1916 | } 1917 | }, 1918 | "node_modules/nwsapi": { 1919 | "version": "2.2.16", 1920 | "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.16.tgz", 1921 | "integrity": "sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==", 1922 | "dev": true, 1923 | "license": "MIT" 1924 | }, 1925 | "node_modules/parse5": { 1926 | "version": "7.2.1", 1927 | "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", 1928 | "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", 1929 | "dev": true, 1930 | "license": "MIT", 1931 | "dependencies": { 1932 | "entities": "^4.5.0" 1933 | }, 1934 | "funding": { 1935 | "url": "https://github.com/inikulin/parse5?sponsor=1" 1936 | } 1937 | }, 1938 | "node_modules/pathe": { 1939 | "version": "2.0.3", 1940 | "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", 1941 | "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", 1942 | "dev": true, 1943 | "license": "MIT" 1944 | }, 1945 | "node_modules/pathval": { 1946 | "version": "2.0.0", 1947 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", 1948 | "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", 1949 | "dev": true, 1950 | "license": "MIT", 1951 | "engines": { 1952 | "node": ">= 14.16" 1953 | } 1954 | }, 1955 | "node_modules/picocolors": { 1956 | "version": "1.1.1", 1957 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", 1958 | "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", 1959 | "dev": true, 1960 | "license": "ISC" 1961 | }, 1962 | "node_modules/picomatch": { 1963 | "version": "2.3.1", 1964 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1965 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1966 | "dev": true, 1967 | "license": "MIT", 1968 | "engines": { 1969 | "node": ">=8.6" 1970 | }, 1971 | "funding": { 1972 | "url": "https://github.com/sponsors/jonschlinkert" 1973 | } 1974 | }, 1975 | "node_modules/postcss": { 1976 | "version": "8.5.2", 1977 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.2.tgz", 1978 | "integrity": "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==", 1979 | "dev": true, 1980 | "funding": [ 1981 | { 1982 | "type": "opencollective", 1983 | "url": "https://opencollective.com/postcss/" 1984 | }, 1985 | { 1986 | "type": "tidelift", 1987 | "url": "https://tidelift.com/funding/github/npm/postcss" 1988 | }, 1989 | { 1990 | "type": "github", 1991 | "url": "https://github.com/sponsors/ai" 1992 | } 1993 | ], 1994 | "license": "MIT", 1995 | "dependencies": { 1996 | "nanoid": "^3.3.8", 1997 | "picocolors": "^1.1.1", 1998 | "source-map-js": "^1.2.1" 1999 | }, 2000 | "engines": { 2001 | "node": "^10 || ^12 || >=14" 2002 | } 2003 | }, 2004 | "node_modules/prompts": { 2005 | "version": "2.4.2", 2006 | "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", 2007 | "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", 2008 | "dev": true, 2009 | "license": "MIT", 2010 | "dependencies": { 2011 | "kleur": "^3.0.3", 2012 | "sisteransi": "^1.0.5" 2013 | }, 2014 | "engines": { 2015 | "node": ">= 6" 2016 | } 2017 | }, 2018 | "node_modules/punycode": { 2019 | "version": "2.3.1", 2020 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", 2021 | "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", 2022 | "dev": true, 2023 | "license": "MIT", 2024 | "engines": { 2025 | "node": ">=6" 2026 | } 2027 | }, 2028 | "node_modules/queue-microtask": { 2029 | "version": "1.2.3", 2030 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 2031 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 2032 | "dev": true, 2033 | "funding": [ 2034 | { 2035 | "type": "github", 2036 | "url": "https://github.com/sponsors/feross" 2037 | }, 2038 | { 2039 | "type": "patreon", 2040 | "url": "https://www.patreon.com/feross" 2041 | }, 2042 | { 2043 | "type": "consulting", 2044 | "url": "https://feross.org/support" 2045 | } 2046 | ], 2047 | "license": "MIT" 2048 | }, 2049 | "node_modules/readdirp": { 2050 | "version": "3.6.0", 2051 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 2052 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 2053 | "dev": true, 2054 | "license": "MIT", 2055 | "dependencies": { 2056 | "picomatch": "^2.2.1" 2057 | }, 2058 | "engines": { 2059 | "node": ">=8.10.0" 2060 | } 2061 | }, 2062 | "node_modules/reusify": { 2063 | "version": "1.0.4", 2064 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 2065 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 2066 | "dev": true, 2067 | "license": "MIT", 2068 | "engines": { 2069 | "iojs": ">=1.0.0", 2070 | "node": ">=0.10.0" 2071 | } 2072 | }, 2073 | "node_modules/rollup": { 2074 | "version": "4.34.8", 2075 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.8.tgz", 2076 | "integrity": "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==", 2077 | "dev": true, 2078 | "license": "MIT", 2079 | "dependencies": { 2080 | "@types/estree": "1.0.6" 2081 | }, 2082 | "bin": { 2083 | "rollup": "dist/bin/rollup" 2084 | }, 2085 | "engines": { 2086 | "node": ">=18.0.0", 2087 | "npm": ">=8.0.0" 2088 | }, 2089 | "optionalDependencies": { 2090 | "@rollup/rollup-android-arm-eabi": "4.34.8", 2091 | "@rollup/rollup-android-arm64": "4.34.8", 2092 | "@rollup/rollup-darwin-arm64": "4.34.8", 2093 | "@rollup/rollup-darwin-x64": "4.34.8", 2094 | "@rollup/rollup-freebsd-arm64": "4.34.8", 2095 | "@rollup/rollup-freebsd-x64": "4.34.8", 2096 | "@rollup/rollup-linux-arm-gnueabihf": "4.34.8", 2097 | "@rollup/rollup-linux-arm-musleabihf": "4.34.8", 2098 | "@rollup/rollup-linux-arm64-gnu": "4.34.8", 2099 | "@rollup/rollup-linux-arm64-musl": "4.34.8", 2100 | "@rollup/rollup-linux-loongarch64-gnu": "4.34.8", 2101 | "@rollup/rollup-linux-powerpc64le-gnu": "4.34.8", 2102 | "@rollup/rollup-linux-riscv64-gnu": "4.34.8", 2103 | "@rollup/rollup-linux-s390x-gnu": "4.34.8", 2104 | "@rollup/rollup-linux-x64-gnu": "4.34.8", 2105 | "@rollup/rollup-linux-x64-musl": "4.34.8", 2106 | "@rollup/rollup-win32-arm64-msvc": "4.34.8", 2107 | "@rollup/rollup-win32-ia32-msvc": "4.34.8", 2108 | "@rollup/rollup-win32-x64-msvc": "4.34.8", 2109 | "fsevents": "~2.3.2" 2110 | } 2111 | }, 2112 | "node_modules/rrweb-cssom": { 2113 | "version": "0.7.1", 2114 | "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", 2115 | "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", 2116 | "dev": true, 2117 | "license": "MIT" 2118 | }, 2119 | "node_modules/run-parallel": { 2120 | "version": "1.2.0", 2121 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 2122 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 2123 | "dev": true, 2124 | "funding": [ 2125 | { 2126 | "type": "github", 2127 | "url": "https://github.com/sponsors/feross" 2128 | }, 2129 | { 2130 | "type": "patreon", 2131 | "url": "https://www.patreon.com/feross" 2132 | }, 2133 | { 2134 | "type": "consulting", 2135 | "url": "https://feross.org/support" 2136 | } 2137 | ], 2138 | "license": "MIT", 2139 | "dependencies": { 2140 | "queue-microtask": "^1.2.2" 2141 | } 2142 | }, 2143 | "node_modules/safer-buffer": { 2144 | "version": "2.1.2", 2145 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 2146 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 2147 | "dev": true, 2148 | "license": "MIT" 2149 | }, 2150 | "node_modules/saxes": { 2151 | "version": "6.0.0", 2152 | "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", 2153 | "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", 2154 | "dev": true, 2155 | "license": "ISC", 2156 | "dependencies": { 2157 | "xmlchars": "^2.2.0" 2158 | }, 2159 | "engines": { 2160 | "node": ">=v12.22.7" 2161 | } 2162 | }, 2163 | "node_modules/siginfo": { 2164 | "version": "2.0.0", 2165 | "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", 2166 | "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", 2167 | "dev": true, 2168 | "license": "ISC" 2169 | }, 2170 | "node_modules/sisteransi": { 2171 | "version": "1.0.5", 2172 | "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", 2173 | "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", 2174 | "dev": true, 2175 | "license": "MIT" 2176 | }, 2177 | "node_modules/source-map-js": { 2178 | "version": "1.2.1", 2179 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", 2180 | "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", 2181 | "dev": true, 2182 | "license": "BSD-3-Clause", 2183 | "engines": { 2184 | "node": ">=0.10.0" 2185 | } 2186 | }, 2187 | "node_modules/stackback": { 2188 | "version": "0.0.2", 2189 | "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", 2190 | "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", 2191 | "dev": true, 2192 | "license": "MIT" 2193 | }, 2194 | "node_modules/std-env": { 2195 | "version": "3.8.0", 2196 | "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz", 2197 | "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==", 2198 | "dev": true, 2199 | "license": "MIT" 2200 | }, 2201 | "node_modules/symbol-tree": { 2202 | "version": "3.2.4", 2203 | "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", 2204 | "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", 2205 | "dev": true, 2206 | "license": "MIT" 2207 | }, 2208 | "node_modules/tinybench": { 2209 | "version": "2.9.0", 2210 | "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", 2211 | "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", 2212 | "dev": true, 2213 | "license": "MIT" 2214 | }, 2215 | "node_modules/tinyexec": { 2216 | "version": "0.3.2", 2217 | "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", 2218 | "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", 2219 | "dev": true, 2220 | "license": "MIT" 2221 | }, 2222 | "node_modules/tinypool": { 2223 | "version": "1.0.2", 2224 | "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", 2225 | "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", 2226 | "dev": true, 2227 | "license": "MIT", 2228 | "engines": { 2229 | "node": "^18.0.0 || >=20.0.0" 2230 | } 2231 | }, 2232 | "node_modules/tinyrainbow": { 2233 | "version": "2.0.0", 2234 | "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", 2235 | "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", 2236 | "dev": true, 2237 | "license": "MIT", 2238 | "engines": { 2239 | "node": ">=14.0.0" 2240 | } 2241 | }, 2242 | "node_modules/tinyspy": { 2243 | "version": "3.0.2", 2244 | "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", 2245 | "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", 2246 | "dev": true, 2247 | "license": "MIT", 2248 | "engines": { 2249 | "node": ">=14.0.0" 2250 | } 2251 | }, 2252 | "node_modules/tldts": { 2253 | "version": "6.1.77", 2254 | "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.77.tgz", 2255 | "integrity": "sha512-lBpoWgy+kYmuXWQ83+R7LlJCnsd9YW8DGpZSHhrMl4b8Ly/1vzOie3OdtmUJDkKxcgRGOehDu5btKkty+JEe+g==", 2256 | "dev": true, 2257 | "license": "MIT", 2258 | "dependencies": { 2259 | "tldts-core": "^6.1.77" 2260 | }, 2261 | "bin": { 2262 | "tldts": "bin/cli.js" 2263 | } 2264 | }, 2265 | "node_modules/tldts-core": { 2266 | "version": "6.1.77", 2267 | "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.77.tgz", 2268 | "integrity": "sha512-bCaqm24FPk8OgBkM0u/SrEWJgHnhBWYqeBo6yUmcZJDCHt/IfyWBb+14CXdGi4RInMv4v7eUAin15W0DoA+Ytg==", 2269 | "dev": true, 2270 | "license": "MIT" 2271 | }, 2272 | "node_modules/to-regex-range": { 2273 | "version": "5.0.1", 2274 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 2275 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2276 | "dev": true, 2277 | "license": "MIT", 2278 | "dependencies": { 2279 | "is-number": "^7.0.0" 2280 | }, 2281 | "engines": { 2282 | "node": ">=8.0" 2283 | } 2284 | }, 2285 | "node_modules/tough-cookie": { 2286 | "version": "5.1.1", 2287 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.1.tgz", 2288 | "integrity": "sha512-Ek7HndSVkp10hmHP9V4qZO1u+pn1RU5sI0Fw+jCU3lyvuMZcgqsNgc6CmJJZyByK4Vm/qotGRJlfgAX8q+4JiA==", 2289 | "dev": true, 2290 | "license": "BSD-3-Clause", 2291 | "dependencies": { 2292 | "tldts": "^6.1.32" 2293 | }, 2294 | "engines": { 2295 | "node": ">=16" 2296 | } 2297 | }, 2298 | "node_modules/tr46": { 2299 | "version": "5.0.0", 2300 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", 2301 | "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", 2302 | "dev": true, 2303 | "license": "MIT", 2304 | "dependencies": { 2305 | "punycode": "^2.3.1" 2306 | }, 2307 | "engines": { 2308 | "node": ">=18" 2309 | } 2310 | }, 2311 | "node_modules/tsconfck": { 2312 | "version": "3.1.5", 2313 | "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.5.tgz", 2314 | "integrity": "sha512-CLDfGgUp7XPswWnezWwsCRxNmgQjhYq3VXHM0/XIRxhVrKw0M1if9agzryh1QS3nxjCROvV+xWxoJO1YctzzWg==", 2315 | "dev": true, 2316 | "license": "MIT", 2317 | "bin": { 2318 | "tsconfck": "bin/tsconfck.js" 2319 | }, 2320 | "engines": { 2321 | "node": "^18 || >=20" 2322 | }, 2323 | "peerDependencies": { 2324 | "typescript": "^5.0.0" 2325 | }, 2326 | "peerDependenciesMeta": { 2327 | "typescript": { 2328 | "optional": true 2329 | } 2330 | } 2331 | }, 2332 | "node_modules/typescript": { 2333 | "version": "5.7.3", 2334 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", 2335 | "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", 2336 | "dev": true, 2337 | "license": "Apache-2.0", 2338 | "bin": { 2339 | "tsc": "bin/tsc", 2340 | "tsserver": "bin/tsserver" 2341 | }, 2342 | "engines": { 2343 | "node": ">=14.17" 2344 | } 2345 | }, 2346 | "node_modules/undici-types": { 2347 | "version": "5.26.5", 2348 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", 2349 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", 2350 | "dev": true, 2351 | "license": "MIT" 2352 | }, 2353 | "node_modules/vite": { 2354 | "version": "6.1.0", 2355 | "resolved": "https://registry.npmjs.org/vite/-/vite-6.1.0.tgz", 2356 | "integrity": "sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==", 2357 | "dev": true, 2358 | "license": "MIT", 2359 | "dependencies": { 2360 | "esbuild": "^0.24.2", 2361 | "postcss": "^8.5.1", 2362 | "rollup": "^4.30.1" 2363 | }, 2364 | "bin": { 2365 | "vite": "bin/vite.js" 2366 | }, 2367 | "engines": { 2368 | "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 2369 | }, 2370 | "funding": { 2371 | "url": "https://github.com/vitejs/vite?sponsor=1" 2372 | }, 2373 | "optionalDependencies": { 2374 | "fsevents": "~2.3.3" 2375 | }, 2376 | "peerDependencies": { 2377 | "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", 2378 | "jiti": ">=1.21.0", 2379 | "less": "*", 2380 | "lightningcss": "^1.21.0", 2381 | "sass": "*", 2382 | "sass-embedded": "*", 2383 | "stylus": "*", 2384 | "sugarss": "*", 2385 | "terser": "^5.16.0", 2386 | "tsx": "^4.8.1", 2387 | "yaml": "^2.4.2" 2388 | }, 2389 | "peerDependenciesMeta": { 2390 | "@types/node": { 2391 | "optional": true 2392 | }, 2393 | "jiti": { 2394 | "optional": true 2395 | }, 2396 | "less": { 2397 | "optional": true 2398 | }, 2399 | "lightningcss": { 2400 | "optional": true 2401 | }, 2402 | "sass": { 2403 | "optional": true 2404 | }, 2405 | "sass-embedded": { 2406 | "optional": true 2407 | }, 2408 | "stylus": { 2409 | "optional": true 2410 | }, 2411 | "sugarss": { 2412 | "optional": true 2413 | }, 2414 | "terser": { 2415 | "optional": true 2416 | }, 2417 | "tsx": { 2418 | "optional": true 2419 | }, 2420 | "yaml": { 2421 | "optional": true 2422 | } 2423 | } 2424 | }, 2425 | "node_modules/vite-node": { 2426 | "version": "3.0.5", 2427 | "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.5.tgz", 2428 | "integrity": "sha512-02JEJl7SbtwSDJdYS537nU6l+ktdvcREfLksk/NDAqtdKWGqHl+joXzEubHROmS3E6pip+Xgu2tFezMu75jH7A==", 2429 | "dev": true, 2430 | "license": "MIT", 2431 | "dependencies": { 2432 | "cac": "^6.7.14", 2433 | "debug": "^4.4.0", 2434 | "es-module-lexer": "^1.6.0", 2435 | "pathe": "^2.0.2", 2436 | "vite": "^5.0.0 || ^6.0.0" 2437 | }, 2438 | "bin": { 2439 | "vite-node": "vite-node.mjs" 2440 | }, 2441 | "engines": { 2442 | "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 2443 | }, 2444 | "funding": { 2445 | "url": "https://opencollective.com/vitest" 2446 | } 2447 | }, 2448 | "node_modules/vite-tsconfig-paths": { 2449 | "version": "5.1.4", 2450 | "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-5.1.4.tgz", 2451 | "integrity": "sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w==", 2452 | "dev": true, 2453 | "license": "MIT", 2454 | "dependencies": { 2455 | "debug": "^4.1.1", 2456 | "globrex": "^0.1.2", 2457 | "tsconfck": "^3.0.3" 2458 | }, 2459 | "peerDependencies": { 2460 | "vite": "*" 2461 | }, 2462 | "peerDependenciesMeta": { 2463 | "vite": { 2464 | "optional": true 2465 | } 2466 | } 2467 | }, 2468 | "node_modules/vitest": { 2469 | "version": "3.0.5", 2470 | "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.5.tgz", 2471 | "integrity": "sha512-4dof+HvqONw9bvsYxtkfUp2uHsTN9bV2CZIi1pWgoFpL1Lld8LA1ka9q/ONSsoScAKG7NVGf2stJTI7XRkXb2Q==", 2472 | "dev": true, 2473 | "license": "MIT", 2474 | "dependencies": { 2475 | "@vitest/expect": "3.0.5", 2476 | "@vitest/mocker": "3.0.5", 2477 | "@vitest/pretty-format": "^3.0.5", 2478 | "@vitest/runner": "3.0.5", 2479 | "@vitest/snapshot": "3.0.5", 2480 | "@vitest/spy": "3.0.5", 2481 | "@vitest/utils": "3.0.5", 2482 | "chai": "^5.1.2", 2483 | "debug": "^4.4.0", 2484 | "expect-type": "^1.1.0", 2485 | "magic-string": "^0.30.17", 2486 | "pathe": "^2.0.2", 2487 | "std-env": "^3.8.0", 2488 | "tinybench": "^2.9.0", 2489 | "tinyexec": "^0.3.2", 2490 | "tinypool": "^1.0.2", 2491 | "tinyrainbow": "^2.0.0", 2492 | "vite": "^5.0.0 || ^6.0.0", 2493 | "vite-node": "3.0.5", 2494 | "why-is-node-running": "^2.3.0" 2495 | }, 2496 | "bin": { 2497 | "vitest": "vitest.mjs" 2498 | }, 2499 | "engines": { 2500 | "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 2501 | }, 2502 | "funding": { 2503 | "url": "https://opencollective.com/vitest" 2504 | }, 2505 | "peerDependencies": { 2506 | "@edge-runtime/vm": "*", 2507 | "@types/debug": "^4.1.12", 2508 | "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", 2509 | "@vitest/browser": "3.0.5", 2510 | "@vitest/ui": "3.0.5", 2511 | "happy-dom": "*", 2512 | "jsdom": "*" 2513 | }, 2514 | "peerDependenciesMeta": { 2515 | "@edge-runtime/vm": { 2516 | "optional": true 2517 | }, 2518 | "@types/debug": { 2519 | "optional": true 2520 | }, 2521 | "@types/node": { 2522 | "optional": true 2523 | }, 2524 | "@vitest/browser": { 2525 | "optional": true 2526 | }, 2527 | "@vitest/ui": { 2528 | "optional": true 2529 | }, 2530 | "happy-dom": { 2531 | "optional": true 2532 | }, 2533 | "jsdom": { 2534 | "optional": true 2535 | } 2536 | } 2537 | }, 2538 | "node_modules/w3c-xmlserializer": { 2539 | "version": "5.0.0", 2540 | "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", 2541 | "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", 2542 | "dev": true, 2543 | "license": "MIT", 2544 | "dependencies": { 2545 | "xml-name-validator": "^5.0.0" 2546 | }, 2547 | "engines": { 2548 | "node": ">=18" 2549 | } 2550 | }, 2551 | "node_modules/webidl-conversions": { 2552 | "version": "7.0.0", 2553 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", 2554 | "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", 2555 | "dev": true, 2556 | "license": "BSD-2-Clause", 2557 | "engines": { 2558 | "node": ">=12" 2559 | } 2560 | }, 2561 | "node_modules/whatwg-encoding": { 2562 | "version": "3.1.1", 2563 | "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", 2564 | "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", 2565 | "dev": true, 2566 | "license": "MIT", 2567 | "dependencies": { 2568 | "iconv-lite": "0.6.3" 2569 | }, 2570 | "engines": { 2571 | "node": ">=18" 2572 | } 2573 | }, 2574 | "node_modules/whatwg-mimetype": { 2575 | "version": "4.0.0", 2576 | "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", 2577 | "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", 2578 | "dev": true, 2579 | "license": "MIT", 2580 | "engines": { 2581 | "node": ">=18" 2582 | } 2583 | }, 2584 | "node_modules/whatwg-url": { 2585 | "version": "14.1.1", 2586 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.1.1.tgz", 2587 | "integrity": "sha512-mDGf9diDad/giZ/Sm9Xi2YcyzaFpbdLpJPr+E9fSkyQ7KpQD4SdFcugkRQYzhmfI4KeV4Qpnn2sKPdo+kmsgRQ==", 2588 | "dev": true, 2589 | "license": "MIT", 2590 | "dependencies": { 2591 | "tr46": "^5.0.0", 2592 | "webidl-conversions": "^7.0.0" 2593 | }, 2594 | "engines": { 2595 | "node": ">=18" 2596 | } 2597 | }, 2598 | "node_modules/why-is-node-running": { 2599 | "version": "2.3.0", 2600 | "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", 2601 | "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", 2602 | "dev": true, 2603 | "license": "MIT", 2604 | "dependencies": { 2605 | "siginfo": "^2.0.0", 2606 | "stackback": "0.0.2" 2607 | }, 2608 | "bin": { 2609 | "why-is-node-running": "cli.js" 2610 | }, 2611 | "engines": { 2612 | "node": ">=8" 2613 | } 2614 | }, 2615 | "node_modules/ws": { 2616 | "version": "8.18.0", 2617 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", 2618 | "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", 2619 | "dev": true, 2620 | "license": "MIT", 2621 | "engines": { 2622 | "node": ">=10.0.0" 2623 | }, 2624 | "peerDependencies": { 2625 | "bufferutil": "^4.0.1", 2626 | "utf-8-validate": ">=5.0.2" 2627 | }, 2628 | "peerDependenciesMeta": { 2629 | "bufferutil": { 2630 | "optional": true 2631 | }, 2632 | "utf-8-validate": { 2633 | "optional": true 2634 | } 2635 | } 2636 | }, 2637 | "node_modules/xml-name-validator": { 2638 | "version": "5.0.0", 2639 | "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", 2640 | "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", 2641 | "dev": true, 2642 | "license": "Apache-2.0", 2643 | "engines": { 2644 | "node": ">=18" 2645 | } 2646 | }, 2647 | "node_modules/xmlchars": { 2648 | "version": "2.2.0", 2649 | "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", 2650 | "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", 2651 | "dev": true, 2652 | "license": "MIT" 2653 | }, 2654 | "node_modules/zod": { 2655 | "version": "3.24.2", 2656 | "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", 2657 | "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", 2658 | "license": "MIT", 2659 | "funding": { 2660 | "url": "https://github.com/sponsors/colinhacks" 2661 | } 2662 | } 2663 | } 2664 | } 2665 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zod-tutorial", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "author": "Matt Pocock ", 6 | "license": "MIT", 7 | "devDependencies": { 8 | "@total-typescript/exercise-cli": "^0.11.0", 9 | "@types/node": "^18.6.5", 10 | "jsdom": "^25.0.0", 11 | "typescript": "^5.6.2", 12 | "vite-tsconfig-paths": "^5.1.4", 13 | "vitest": "^3.0.5" 14 | }, 15 | "scripts": { 16 | "exercise": "tt-cli run", 17 | "e": "npm run exercise", 18 | "solution": "tt-cli run --solution", 19 | "s": "npm run solution", 20 | "update-snapshots": "(cd scripts/tests && npx vitest run -u)", 21 | "ci": "(cd scripts/tests && npx vitest run)", 22 | "prepare": "tt-cli prepare-stackblitz", 23 | "e-01": "tt-cli run 01", 24 | "s-01": "tt-cli run 01 --solution", 25 | "e-02": "tt-cli run 02", 26 | "s-02": "tt-cli run 02 --solution", 27 | "e-03": "tt-cli run 03", 28 | "s-03": "tt-cli run 03 --solution", 29 | "e-04": "tt-cli run 04", 30 | "s-04": "tt-cli run 04 --solution", 31 | "e-05": "tt-cli run 05", 32 | "s-05": "tt-cli run 05 --solution", 33 | "e-06": "tt-cli run 06", 34 | "s-06": "tt-cli run 06 --solution", 35 | "e-07": "tt-cli run 07", 36 | "s-07": "tt-cli run 07 --solution", 37 | "e-08": "tt-cli run 08", 38 | "s-08": "tt-cli run 08 --solution", 39 | "e-09": "tt-cli run 09", 40 | "s-09": "tt-cli run 09 --solution", 41 | "e-10": "tt-cli run 10", 42 | "s-10": "tt-cli run 10 --solution" 43 | }, 44 | "dependencies": { 45 | "zod": "^3.23.8" 46 | }, 47 | "type": "module" 48 | } -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["config:base"], 4 | "packageRules": [ 5 | { 6 | "packagePatterns": ["*"], 7 | "excludePackagePatterns": [ 8 | "typescript", 9 | "vitest", 10 | "jsdom", 11 | "prettier", 12 | "vite-tsconfig-paths", 13 | "react", 14 | "@types/react", 15 | "@total-typescript/exercise-cli", 16 | "zod" 17 | ], 18 | "enabled": false 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /src/01-number.problem.ts: -------------------------------------------------------------------------------- 1 | // CODE 2 | 3 | import { expect, it } from "vitest"; 4 | import { z } from "zod"; 5 | // ^ 🕵️‍♂️ 6 | 7 | export const toString = (num: unknown) => { 8 | return String(num); 9 | }; 10 | 11 | // TESTS 12 | 13 | it("Should throw a runtime error when called with not a number", () => { 14 | expect(() => toString("123")).toThrowError( 15 | "Expected number, received string", 16 | ); 17 | }); 18 | 19 | it("Should return a string when called with a number", () => { 20 | expect(toString(1)).toBeTypeOf("string"); 21 | }); 22 | -------------------------------------------------------------------------------- /src/01-number.solution.ts: -------------------------------------------------------------------------------- 1 | // CODE 2 | 3 | import { expect, it } from "vitest"; 4 | import { z } from "zod"; 5 | 6 | const numberParser = z.number(); 7 | 8 | export const toString = (num: unknown) => { 9 | const parsed = numberParser.parse(num); 10 | return String(parsed); 11 | }; 12 | 13 | // TESTS 14 | 15 | it("Should throw a runtime error when called with not a number", () => { 16 | expect(() => toString("123")).toThrowError( 17 | "Expected number, received string", 18 | ); 19 | }); 20 | 21 | it("Should return a string when called with a number", () => { 22 | expect(toString(1)).toBeTypeOf("string"); 23 | }); 24 | -------------------------------------------------------------------------------- /src/02-object.problem.ts: -------------------------------------------------------------------------------- 1 | // CODE 2 | 3 | import { expect, it } from "vitest"; 4 | import { z } from "zod"; 5 | 6 | const PersonResult = z.unknown(); 7 | // ^ 🕵️‍♂️ 8 | 9 | export const fetchStarWarsPersonName = async (id: string) => { 10 | const data = await fetch( 11 | "https://www.totaltypescript.com/swapi/people/" + id + ".json", 12 | ).then((res) => res.json()); 13 | 14 | const parsedData = PersonResult.parse(data); 15 | 16 | return parsedData.name; 17 | }; 18 | 19 | // TESTS 20 | 21 | it("Should return the name", async () => { 22 | expect(await fetchStarWarsPersonName("1")).toEqual("Luke Skywalker"); 23 | expect(await fetchStarWarsPersonName("2")).toEqual("C-3PO"); 24 | }); 25 | -------------------------------------------------------------------------------- /src/02-object.solution.ts: -------------------------------------------------------------------------------- 1 | // CODE 2 | 3 | import { expect, it } from "vitest"; 4 | import { z } from "zod"; 5 | 6 | const PersonResult = z.object({ 7 | name: z.string(), 8 | }); 9 | 10 | export const fetchStarWarsPersonName = async (id: string) => { 11 | const data = await fetch( 12 | "https://www.totaltypescript.com/swapi/people/" + id + ".json", 13 | ).then((res) => res.json()); 14 | 15 | const parsedData = PersonResult.parse(data); 16 | 17 | return parsedData.name; 18 | }; 19 | 20 | // TESTS 21 | 22 | it("Should return the name", async () => { 23 | expect(await fetchStarWarsPersonName("1")).toEqual("Luke Skywalker"); 24 | expect(await fetchStarWarsPersonName("2")).toEqual("C-3PO"); 25 | }); 26 | -------------------------------------------------------------------------------- /src/03-array.problem.ts: -------------------------------------------------------------------------------- 1 | // CODE 2 | 3 | import { expect, it } from "vitest"; 4 | import { z } from "zod"; 5 | 6 | const StarWarsPerson = z.object({ 7 | name: z.string(), 8 | }); 9 | 10 | const StarWarsPeopleResults = z.unknown(); 11 | // ^ 🕵️‍♂️ 12 | 13 | export const fetchStarWarsPeople = async () => { 14 | const data = await fetch( 15 | "https://www.totaltypescript.com/swapi/people.json", 16 | ).then((res) => res.json()); 17 | 18 | const parsedData = StarWarsPeopleResults.parse(data); 19 | 20 | return parsedData.results; 21 | }; 22 | 23 | // TESTS 24 | 25 | it("Should return the name", async () => { 26 | expect((await fetchStarWarsPeople())[0]).toEqual({ 27 | name: "Luke Skywalker", 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /src/03-array.solution.ts: -------------------------------------------------------------------------------- 1 | // CODE 2 | 3 | import { expect, it } from "vitest"; 4 | import { z } from "zod"; 5 | 6 | const StarWarsPerson = z.object({ 7 | name: z.string(), 8 | }); 9 | 10 | const StarWarsPeopleResults = z.object({ 11 | results: z.array(StarWarsPerson), 12 | }); 13 | 14 | export const fetchStarWarsPeople = async () => { 15 | const data = await fetch( 16 | "https://www.totaltypescript.com/swapi/people.json", 17 | ).then((res) => res.json()); 18 | 19 | const parsedData = StarWarsPeopleResults.parse(data); 20 | 21 | return parsedData.results; 22 | }; 23 | 24 | // TESTS 25 | 26 | it("Should return the name", async () => { 27 | expect((await fetchStarWarsPeople())[0]).toEqual({ 28 | name: "Luke Skywalker", 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /src/04-infer.problem.ts: -------------------------------------------------------------------------------- 1 | // CODE 2 | 3 | import { z } from "zod"; 4 | 5 | const StarWarsPerson = z.object({ 6 | name: z.string(), 7 | }); 8 | 9 | const StarWarsPeopleResults = z.object({ 10 | results: z.array(StarWarsPerson), 11 | }); 12 | 13 | const logStarWarsPeopleResults = (data: unknown) => { 14 | // ^ 🕵️‍♂️ 15 | data.results.map((person) => { 16 | console.log(person.name); 17 | }); 18 | }; 19 | -------------------------------------------------------------------------------- /src/04-infer.solution.1.ts: -------------------------------------------------------------------------------- 1 | // CODE 2 | 3 | import { z } from "zod"; 4 | 5 | const StarWarsPerson = z.object({ 6 | name: z.string(), 7 | }); 8 | 9 | const StarWarsPeopleResults = z.object({ 10 | results: z.array(StarWarsPerson), 11 | }); 12 | 13 | const logStarWarsPeopleResults = ( 14 | data: z.infer, 15 | ) => { 16 | data.results.map((person) => { 17 | console.log(person.name); 18 | }); 19 | }; 20 | -------------------------------------------------------------------------------- /src/04-infer.solution.2.ts: -------------------------------------------------------------------------------- 1 | // CODE 2 | 3 | import { z } from "zod"; 4 | 5 | const StarWarsPerson = z.object({ 6 | name: z.string(), 7 | }); 8 | 9 | const StarWarsPeopleResults = z.object({ 10 | results: z.array(StarWarsPerson), 11 | }); 12 | 13 | type StarWarsPeopleResultsType = z.infer; 14 | 15 | const logStarWarsPeopleResults = (data: StarWarsPeopleResultsType) => { 16 | data.results.map((person) => { 17 | console.log(person.name); 18 | }); 19 | }; 20 | -------------------------------------------------------------------------------- /src/05-optional.problem.ts: -------------------------------------------------------------------------------- 1 | // CODE 2 | 3 | import { expect, it } from "vitest"; 4 | import { z } from "zod"; 5 | 6 | const Form = z.object({ 7 | name: z.string(), 8 | phoneNumber: z.string(), 9 | // ^ 🕵️‍♂️ 10 | }); 11 | 12 | export const validateFormInput = (values: unknown) => { 13 | const parsedData = Form.parse(values); 14 | 15 | return parsedData; 16 | }; 17 | 18 | // TESTS 19 | 20 | it("Should validate correct inputs", async () => { 21 | expect(() => 22 | validateFormInput({ 23 | name: "Matt", 24 | }), 25 | ).not.toThrow(); 26 | 27 | expect(() => 28 | validateFormInput({ 29 | name: "Matt", 30 | phoneNumber: "123", 31 | }), 32 | ).not.toThrow(); 33 | }); 34 | 35 | it("Should throw when you do not include the name", async () => { 36 | expect(() => validateFormInput({})).toThrowError("Required"); 37 | }); 38 | -------------------------------------------------------------------------------- /src/05-optional.solution.ts: -------------------------------------------------------------------------------- 1 | // CODE 2 | 3 | import { expect, it } from "vitest"; 4 | import { z } from "zod"; 5 | 6 | const Form = z.object({ 7 | name: z.string(), 8 | phoneNumber: z.string().optional(), 9 | }); 10 | 11 | export const validateFormInput = (values: unknown) => { 12 | const parsedData = Form.parse(values); 13 | 14 | return parsedData; 15 | }; 16 | 17 | // TESTS 18 | 19 | it("Should validate correct inputs", async () => { 20 | expect(() => 21 | validateFormInput({ 22 | name: "Matt", 23 | }), 24 | ).not.toThrow(); 25 | 26 | expect(() => 27 | validateFormInput({ 28 | name: "Matt", 29 | phoneNumber: "123", 30 | }), 31 | ).not.toThrow(); 32 | }); 33 | 34 | it("Should throw when you do not include the name", async () => { 35 | expect(() => validateFormInput({})).toThrowError("Required"); 36 | }); 37 | -------------------------------------------------------------------------------- /src/06-default.problem.ts: -------------------------------------------------------------------------------- 1 | // CODE 2 | 3 | import { expect, it } from "vitest"; 4 | import { z } from "zod"; 5 | 6 | const Form = z.object({ 7 | repoName: z.string(), 8 | keywords: z.array(z.string()).optional(), 9 | // ^ 🕵️‍♂️ 10 | }); 11 | 12 | export const validateFormInput = (values: unknown) => { 13 | const parsedData = Form.parse(values); 14 | 15 | return parsedData; 16 | }; 17 | 18 | // TESTS 19 | 20 | it("Should include keywords if passed", async () => { 21 | const result = validateFormInput({ 22 | repoName: "mattpocock", 23 | keywords: ["123"], 24 | }); 25 | 26 | expect(result.keywords).toEqual(["123"]); 27 | }); 28 | 29 | it("Should automatically add keywords if none are passed", async () => { 30 | const result = validateFormInput({ 31 | repoName: "mattpocock", 32 | }); 33 | 34 | expect(result.keywords).toEqual([]); 35 | }); 36 | -------------------------------------------------------------------------------- /src/06-default.solution.ts: -------------------------------------------------------------------------------- 1 | // CODE 2 | 3 | import { expect, it } from "vitest"; 4 | import { z } from "zod"; 5 | 6 | const Form = z.object({ 7 | repoName: z.string(), 8 | keywords: z.array(z.string()).default([]), 9 | }); 10 | 11 | export const validateFormInput = (values: unknown) => { 12 | const parsedData = Form.parse(values); 13 | 14 | return parsedData; 15 | }; 16 | 17 | // TESTS 18 | 19 | it("Should include keywords if passed", async () => { 20 | const result = validateFormInput({ 21 | repoName: "mattpocock", 22 | keywords: ["123"], 23 | }); 24 | 25 | expect(result.keywords).toEqual(["123"]); 26 | }); 27 | 28 | it("Should automatically add keywords if none are passed", async () => { 29 | const result = validateFormInput({ 30 | repoName: "mattpocock", 31 | }); 32 | 33 | expect(result.keywords).toEqual([]); 34 | }); 35 | -------------------------------------------------------------------------------- /src/07-union.problem.ts: -------------------------------------------------------------------------------- 1 | // CODE 2 | 3 | import { expect, it } from "vitest"; 4 | import { z } from "zod"; 5 | 6 | const Form = z.object({ 7 | repoName: z.string(), 8 | privacyLevel: z.string(), 9 | // ^ 🕵️‍♂️ 10 | }); 11 | 12 | export const validateFormInput = (values: unknown) => { 13 | const parsedData = Form.parse(values); 14 | 15 | return parsedData; 16 | }; 17 | 18 | // TESTS 19 | 20 | it("Should fail if an invalid privacyLevel passed", async () => { 21 | expect(() => 22 | validateFormInput({ 23 | repoName: "mattpocock", 24 | privacyLevel: "something-not-allowed", 25 | }), 26 | ).toThrowError(); 27 | }); 28 | 29 | it("Should permit valid privacy levels", async () => { 30 | expect( 31 | validateFormInput({ 32 | repoName: "mattpocock", 33 | privacyLevel: "private", 34 | }).privacyLevel, 35 | ).toEqual("private"); 36 | 37 | expect( 38 | validateFormInput({ 39 | repoName: "mattpocock", 40 | privacyLevel: "public", 41 | }).privacyLevel, 42 | ).toEqual("public"); 43 | }); 44 | -------------------------------------------------------------------------------- /src/07-union.solution.1.ts: -------------------------------------------------------------------------------- 1 | // CODE 2 | 3 | import { expect, it } from "vitest"; 4 | import { z } from "zod"; 5 | 6 | const Form = z.object({ 7 | repoName: z.string(), 8 | privacyLevel: z.union([z.literal("private"), z.literal("public")]), 9 | }); 10 | 11 | export const validateFormInput = (values: unknown) => { 12 | const parsedData = Form.parse(values); 13 | 14 | return parsedData; 15 | }; 16 | 17 | // TESTS 18 | 19 | it("Should fail if an invalid privacyLevel passed", async () => { 20 | expect(() => 21 | validateFormInput({ 22 | repoName: "mattpocock", 23 | privacyLevel: "something-not-allowed", 24 | }), 25 | ).toThrowError(); 26 | }); 27 | 28 | it("Should permit valid privacy levels", async () => { 29 | expect( 30 | validateFormInput({ 31 | repoName: "mattpocock", 32 | privacyLevel: "private", 33 | }).privacyLevel, 34 | ).toEqual("private"); 35 | 36 | expect( 37 | validateFormInput({ 38 | repoName: "mattpocock", 39 | privacyLevel: "public", 40 | }).privacyLevel, 41 | ).toEqual("public"); 42 | }); 43 | -------------------------------------------------------------------------------- /src/07-union.solution.2.ts: -------------------------------------------------------------------------------- 1 | // CODE 2 | 3 | import { expect, it } from "vitest"; 4 | import { z } from "zod"; 5 | 6 | const Form = z.object({ 7 | repoName: z.string(), 8 | privacyLevel: z.enum(["private", "public"]), 9 | }); 10 | 11 | export const validateFormInput = (values: unknown) => { 12 | const parsedData = Form.parse(values); 13 | 14 | return parsedData; 15 | }; 16 | 17 | // TESTS 18 | 19 | it("Should fail if an invalid privacyLevel passed", async () => { 20 | expect(() => 21 | validateFormInput({ 22 | repoName: "mattpocock", 23 | privacyLevel: "something-not-allowed", 24 | }), 25 | ).toThrowError(); 26 | }); 27 | 28 | it("Should permit valid privacy levels", async () => { 29 | expect( 30 | validateFormInput({ 31 | repoName: "mattpocock", 32 | privacyLevel: "private", 33 | }).privacyLevel, 34 | ).toEqual("private"); 35 | 36 | expect( 37 | validateFormInput({ 38 | repoName: "mattpocock", 39 | privacyLevel: "public", 40 | }).privacyLevel, 41 | ).toEqual("public"); 42 | }); 43 | -------------------------------------------------------------------------------- /src/08-validations.problem.ts: -------------------------------------------------------------------------------- 1 | // CODE 2 | 3 | import { expect, it } from "vitest"; 4 | import { z } from "zod"; 5 | 6 | const Form = z.object({ 7 | name: z.string(), 8 | // ^ 🕵️‍♂️ 9 | phoneNumber: z.string().optional(), 10 | // ^ 🕵️‍♂️ 11 | email: z.string(), 12 | // ^ 🕵️‍♂️ 13 | website: z.string().optional(), 14 | // ^ 🕵️‍♂️ 15 | }); 16 | 17 | export const validateFormInput = (values: unknown) => { 18 | const parsedData = Form.parse(values); 19 | 20 | return parsedData; 21 | }; 22 | 23 | // TESTS 24 | 25 | it("Should fail if you pass a phone number with too few characters", async () => { 26 | expect(() => 27 | validateFormInput({ 28 | name: "Matt", 29 | email: "matt@example.com", 30 | phoneNumber: "1", 31 | }), 32 | ).toThrowError("String must contain at least 5 character(s)"); 33 | }); 34 | 35 | it("Should fail if you pass a phone number with too many characters", async () => { 36 | expect(() => 37 | validateFormInput({ 38 | name: "Matt", 39 | email: "matt@example.com", 40 | phoneNumber: "1238712387612387612837612873612387162387", 41 | }), 42 | ).toThrowError("String must contain at most 20 character(s)"); 43 | }); 44 | 45 | it("Should throw when you pass an invalid email", async () => { 46 | expect(() => 47 | validateFormInput({ 48 | name: "Matt", 49 | email: "matt", 50 | }), 51 | ).toThrowError("Invalid email"); 52 | }); 53 | 54 | it("Should throw when you pass an invalid website URL", async () => { 55 | expect(() => 56 | validateFormInput({ 57 | name: "Matt", 58 | email: "matt@example.com", 59 | website: "/", 60 | }), 61 | ).toThrowError("Invalid url"); 62 | }); 63 | 64 | it("Should pass when you pass a valid website URL", async () => { 65 | expect(() => 66 | validateFormInput({ 67 | name: "Matt", 68 | email: "matt@example.com", 69 | website: "https://mattpocock.com", 70 | }), 71 | ).not.toThrowError(); 72 | }); 73 | -------------------------------------------------------------------------------- /src/08-validations.solution.ts: -------------------------------------------------------------------------------- 1 | // CODE 2 | 3 | import { expect, it } from "vitest"; 4 | import { z } from "zod"; 5 | 6 | const Form = z.object({ 7 | name: z.string().min(1), 8 | phoneNumber: z.string().min(5).max(20).optional(), 9 | email: z.string().email(), 10 | website: z.string().url().optional(), 11 | }); 12 | 13 | export const validateFormInput = (values: unknown) => { 14 | const parsedData = Form.parse(values); 15 | 16 | return parsedData; 17 | }; 18 | 19 | // TESTS 20 | 21 | it("Should fail if you pass a phone number with too few characters", async () => { 22 | expect(() => 23 | validateFormInput({ 24 | name: "Matt", 25 | email: "matt@example.com", 26 | phoneNumber: "1", 27 | }), 28 | ).toThrowError("String must contain at least 5 character(s)"); 29 | }); 30 | 31 | it("Should fail if you pass a phone number with too many characters", async () => { 32 | expect(() => 33 | validateFormInput({ 34 | name: "Matt", 35 | email: "matt@example.com", 36 | phoneNumber: "1238712387612387612837612873612387162387", 37 | }), 38 | ).toThrowError("String must contain at most 20 character(s)"); 39 | }); 40 | 41 | it("Should throw when you pass an invalid email", async () => { 42 | expect(() => 43 | validateFormInput({ 44 | name: "Matt", 45 | email: "matt", 46 | }), 47 | ).toThrowError("Invalid email"); 48 | }); 49 | 50 | it("Should throw when you pass an invalid website URL", async () => { 51 | expect(() => 52 | validateFormInput({ 53 | name: "Matt", 54 | email: "matt@example.com", 55 | website: "/", 56 | }), 57 | ).toThrowError("Invalid url"); 58 | }); 59 | 60 | it("Should pass when you pass a valid website URL", async () => { 61 | expect(() => 62 | validateFormInput({ 63 | name: "Matt", 64 | email: "matt@example.com", 65 | website: "https://mattpocock.com", 66 | }), 67 | ).not.toThrowError(); 68 | }); 69 | -------------------------------------------------------------------------------- /src/09-composing-objects.problem.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | import { Equal, Expect } from "./helpers/type-utils"; 3 | 4 | /** 5 | * 🕵️‍♂️ Refactor this code below to reduce the duplication, 6 | * while also making sure the cases don't go red! 7 | */ 8 | 9 | const User = z.object({ 10 | id: z.string().uuid(), 11 | name: z.string(), 12 | }); 13 | 14 | const Post = z.object({ 15 | id: z.string().uuid(), 16 | title: z.string(), 17 | body: z.string(), 18 | }); 19 | 20 | const Comment = z.object({ 21 | id: z.string().uuid(), 22 | text: z.string(), 23 | }); 24 | 25 | type cases = [ 26 | Expect, { id: string; text: string }>>, 27 | Expect< 28 | Equal, { id: string; title: string; body: string }> 29 | >, 30 | Expect, { id: string; name: string }>>, 31 | ]; 32 | -------------------------------------------------------------------------------- /src/09-composing-objects.solution.1.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | import { Equal, Expect } from "./helpers/type-utils"; 3 | 4 | const Id = z.string().uuid(); 5 | 6 | const User = z.object({ 7 | id: Id, 8 | name: z.string(), 9 | }); 10 | 11 | const Post = z.object({ 12 | id: Id, 13 | title: z.string(), 14 | body: z.string(), 15 | }); 16 | 17 | const Comment = z.object({ 18 | id: Id, 19 | text: z.string(), 20 | }); 21 | 22 | type cases = [ 23 | Expect, { id: string; text: string }>>, 24 | Expect< 25 | Equal, { id: string; title: string; body: string }> 26 | >, 27 | Expect, { id: string; name: string }>>, 28 | ]; 29 | -------------------------------------------------------------------------------- /src/09-composing-objects.solution.2.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | import { Equal, Expect } from "./helpers/type-utils"; 3 | 4 | const ObjectWithId = z.object({ 5 | id: z.string().uuid(), 6 | }); 7 | 8 | const User = ObjectWithId.extend({ 9 | name: z.string(), 10 | }); 11 | 12 | const Post = ObjectWithId.extend({ 13 | title: z.string(), 14 | body: z.string(), 15 | }); 16 | 17 | const Comment = ObjectWithId.extend({ 18 | text: z.string(), 19 | }); 20 | 21 | type cases = [ 22 | Expect, { id: string; text: string }>>, 23 | Expect< 24 | Equal, { id: string; title: string; body: string }> 25 | >, 26 | Expect, { id: string; name: string }>>, 27 | ]; 28 | -------------------------------------------------------------------------------- /src/09-composing-objects.solution.3.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | import { Equal, Expect } from "./helpers/type-utils"; 3 | 4 | const ObjectWithId = z.object({ 5 | id: z.string().uuid(), 6 | }); 7 | 8 | const User = ObjectWithId.merge( 9 | z.object({ 10 | name: z.string(), 11 | }), 12 | ); 13 | 14 | const Post = ObjectWithId.merge( 15 | z.object({ 16 | title: z.string(), 17 | body: z.string(), 18 | }), 19 | ); 20 | 21 | const Comment = ObjectWithId.merge( 22 | z.object({ 23 | text: z.string(), 24 | }), 25 | ); 26 | 27 | type cases = [ 28 | Expect, { id: string; text: string }>>, 29 | Expect< 30 | Equal, { id: string; title: string; body: string }> 31 | >, 32 | Expect, { id: string; name: string }>>, 33 | ]; 34 | -------------------------------------------------------------------------------- /src/10-transform.problem.ts: -------------------------------------------------------------------------------- 1 | // CODE 2 | 3 | import { expect, it } from "vitest"; 4 | import { z } from "zod"; 5 | 6 | const StarWarsPerson = z.object({ 7 | name: z.string(), 8 | }); 9 | //^ 🕵️‍♂️ 10 | 11 | const StarWarsPeopleResults = z.object({ 12 | results: z.array(StarWarsPerson), 13 | }); 14 | 15 | export const fetchStarWarsPeople = async () => { 16 | const data = await fetch( 17 | "https://www.totaltypescript.com/swapi/people.json", 18 | ).then((res) => res.json()); 19 | 20 | const parsedData = StarWarsPeopleResults.parse(data); 21 | 22 | return parsedData.results; 23 | }; 24 | 25 | // TESTS 26 | 27 | it("Should resolve the name and nameAsArray", async () => { 28 | expect((await fetchStarWarsPeople())[0]).toEqual({ 29 | name: "Luke Skywalker", 30 | nameAsArray: ["Luke", "Skywalker"], 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /src/10-transform.solution.ts: -------------------------------------------------------------------------------- 1 | // CODE 2 | 3 | import { expect, it } from "vitest"; 4 | import { z } from "zod"; 5 | 6 | const StarWarsPerson = z 7 | .object({ 8 | name: z.string(), 9 | }) 10 | .transform((person) => ({ 11 | ...person, 12 | nameAsArray: person.name.split(" "), 13 | })); 14 | 15 | const StarWarsPeopleResults = z.object({ 16 | results: z.array(StarWarsPerson), 17 | }); 18 | 19 | export const fetchStarWarsPeople = async () => { 20 | const data = await fetch( 21 | "https://www.totaltypescript.com/swapi/people.json", 22 | ).then((res) => res.json()); 23 | 24 | const parsedData = StarWarsPeopleResults.parse(data); 25 | 26 | return parsedData.results; 27 | }; 28 | 29 | // TESTS 30 | 31 | it("Should resolve the name and nameAsArray", async () => { 32 | expect((await fetchStarWarsPeople())[0]).toEqual({ 33 | name: "Luke Skywalker", 34 | nameAsArray: ["Luke", "Skywalker"], 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /src/helpers/type-utils.ts: -------------------------------------------------------------------------------- 1 | export type Expect = T; 2 | export type ExpectTrue = T; 3 | export type ExpectFalse = T; 4 | export type IsTrue = T; 5 | export type IsFalse = T; 6 | 7 | export type Equal = (() => T extends X ? 1 : 2) extends < 8 | T, 9 | >() => T extends Y ? 1 : 2 10 | ? true 11 | : false; 12 | export type NotEqual = true extends Equal ? false : true; 13 | 14 | // https://stackoverflow.com/questions/49927523/disallow-call-with-any/49928360#49928360 15 | export type IsAny = 0 extends 1 & T ? true : false; 16 | export type NotAny = true extends IsAny ? false : true; 17 | 18 | export type Debug = { [K in keyof T]: T[K] }; 19 | export type MergeInsertions = T extends object 20 | ? { [K in keyof T]: MergeInsertions } 21 | : T; 22 | 23 | export type Alike = Equal, MergeInsertions>; 24 | 25 | export type ExpectExtends = EXPECTED extends VALUE 26 | ? true 27 | : false; 28 | export type ExpectValidArgs< 29 | FUNC extends (...args: any[]) => any, 30 | ARGS extends any[], 31 | > = ARGS extends Parameters ? true : false; 32 | 33 | export type UnionToIntersection = ( 34 | U extends any ? (k: U) => void : never 35 | ) extends (k: infer I) => void 36 | ? I 37 | : never; 38 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "types": [ 4 | "vitest/importMeta" 5 | ], 6 | "target": "esnext", 7 | "module": "esnext", 8 | "moduleResolution": "node", 9 | "noEmit": true, 10 | "isolatedModules": true, 11 | "esModuleInterop": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "strict": true, 14 | "skipLibCheck": true 15 | }, 16 | "include": [ 17 | "src" 18 | ] 19 | } -------------------------------------------------------------------------------- /vite.config.mts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config"; 2 | import tsconfigPaths from "vite-tsconfig-paths"; 3 | 4 | export default defineConfig({ 5 | test: { 6 | include: ["src/**/*{problem,solution,explainer}*.{ts,tsx}"], 7 | passWithNoTests: true, 8 | environment: "jsdom", 9 | }, 10 | plugins: [tsconfigPaths()], 11 | }); 12 | --------------------------------------------------------------------------------