From 94e63aab619efa163420497d92188c1adfccfd08 Mon Sep 17 00:00:00 2001 From: Dominik Zogg Date: Thu, 29 Feb 2024 21:56:26 +0100 Subject: [PATCH] initial commit --- .env.development | 1 + .env.production | 1 + .env.test | 1 + .eslintrc.cjs | 36 + .github/workflows/ci.yml | 62 + .gitignore | 26 + README.md | 41 + index.html | 13 + package.json | 66 + pnpm-lock.yaml | 3964 +++++++++++++++++ postcss.config.js | 7 + sonar-project.properties | 10 + src/api-client/error.ts | 44 + src/api-client/pet.ts | 166 + src/app.tsx | 46 + src/component/button.tsx | 47 + src/component/form/form.tsx | 49 + src/component/form/pet-filters-form.tsx | 63 + src/component/form/pet-form.tsx | 114 + src/component/heading.tsx | 9 + src/component/page/home.tsx | 20 + src/component/page/not-found.tsx | 20 + src/component/page/pet/create.tsx | 54 + src/component/page/pet/list.tsx | 217 + src/component/page/pet/read.tsx | 87 + src/component/page/pet/update.tsx | 84 + src/component/partial/http-error.tsx | 27 + src/component/partial/pagination.tsx | 115 + src/component/table.tsx | 80 + .../invalid-parameter-by-name-denormalizer.ts | 18 + src/index.css | 10 + src/index.tsx | 15 + src/model/model.ts | 53 + src/routes.tsx | 24 + src/vite-env.d.ts | 1 + tailwind.config.js | 10 + tests/api-client/pet.test.ts | 826 ++++ tests/app.test.tsx | 102 + .../component/form/pet-filters-form.test.tsx | 182 + tests/component/page/home.test.tsx | 19 + tests/component/page/not-found.test.tsx | 21 + tests/component/page/pet/create.test.tsx | 245 + tests/component/page/pet/read.test.tsx | 148 + tests/component/page/pet/update.test.tsx | 364 ++ tests/component/partial/http-error.test.tsx | 49 + tests/component/partial/pagination.test.tsx | 323 ++ ...lid-parameter-by-name-denormalizer.test.ts | 32 + tests/formatter.ts | 5 + tests/routes.test.tsx | 207 + tsconfig.json | 26 + tsconfig.node.json | 11 + vite.config.ts | 23 + vitest.setup.ts | 1 + 53 files changed, 8185 insertions(+) create mode 100644 .env.development create mode 100644 .env.production create mode 100644 .env.test create mode 100644 .eslintrc.cjs create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore create mode 100644 README.md create mode 100644 index.html create mode 100644 package.json create mode 100644 pnpm-lock.yaml create mode 100644 postcss.config.js create mode 100644 sonar-project.properties create mode 100644 src/api-client/error.ts create mode 100644 src/api-client/pet.ts create mode 100644 src/app.tsx create mode 100644 src/component/button.tsx create mode 100644 src/component/form/form.tsx create mode 100644 src/component/form/pet-filters-form.tsx create mode 100644 src/component/form/pet-form.tsx create mode 100644 src/component/heading.tsx create mode 100644 src/component/page/home.tsx create mode 100644 src/component/page/not-found.tsx create mode 100644 src/component/page/pet/create.tsx create mode 100644 src/component/page/pet/list.tsx create mode 100644 src/component/page/pet/read.tsx create mode 100644 src/component/page/pet/update.tsx create mode 100644 src/component/partial/http-error.tsx create mode 100644 src/component/partial/pagination.tsx create mode 100644 src/component/table.tsx create mode 100644 src/denormalizer/invalid-parameter-by-name-denormalizer.ts create mode 100644 src/index.css create mode 100644 src/index.tsx create mode 100644 src/model/model.ts create mode 100644 src/routes.tsx create mode 100644 src/vite-env.d.ts create mode 100644 tailwind.config.js create mode 100644 tests/api-client/pet.test.ts create mode 100644 tests/app.test.tsx create mode 100644 tests/component/form/pet-filters-form.test.tsx create mode 100644 tests/component/page/home.test.tsx create mode 100644 tests/component/page/not-found.test.tsx create mode 100644 tests/component/page/pet/create.test.tsx create mode 100644 tests/component/page/pet/read.test.tsx create mode 100644 tests/component/page/pet/update.test.tsx create mode 100644 tests/component/partial/http-error.test.tsx create mode 100644 tests/component/partial/pagination.test.tsx create mode 100644 tests/denormalizer/invalid-parameter-by-name-denormalizer.test.ts create mode 100644 tests/formatter.ts create mode 100644 tests/routes.test.tsx create mode 100644 tsconfig.json create mode 100644 tsconfig.node.json create mode 100644 vite.config.ts create mode 100644 vitest.setup.ts diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..dbd559c --- /dev/null +++ b/.env.development @@ -0,0 +1 @@ +VITE_PETSTORE_URL=https://localhost diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..994acdd --- /dev/null +++ b/.env.production @@ -0,0 +1 @@ +VITE_PETSTORE_URL=https://petstore.production diff --git a/.env.test b/.env.test new file mode 100644 index 0000000..9104501 --- /dev/null +++ b/.env.test @@ -0,0 +1 @@ +VITE_PETSTORE_URL=https://petstore.test diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..e92ae20 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,36 @@ +module.exports = { + "env": { + "browser": true, + "es2020": true + }, + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:solid/recommended", + "plugin:solid/typescript", + ], + "overrides": [ + { + "env": { + "node": true + }, + "files": [ + ".eslintrc.{js,cjs}" + ], + "parserOptions": { + "sourceType": "script" + } + } + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "plugins": [ + "@typescript-eslint", + "solid" + ], + "rules": { + } +}; diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..3e2bf3e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,62 @@ +name: CI + +on: + push: + pull_request: + branches: + - master + schedule: + - cron: '0 0 * * *' + +jobs: + node16: + name: Node 16 + runs-on: ubuntu-22.04 + steps: + - name: checkout + uses: actions/checkout@v4 + - name: checkout node + uses: actions/setup-node@v4 + with: + node-version: '16' + - run: npm install -g pnpm@latest + - run: pnpm install + - run: pnpm run build + - run: TZ=Europe/Zurich pnpm test -- --coverage + node18: + name: Node 18 + runs-on: ubuntu-22.04 + steps: + - name: checkout + uses: actions/checkout@v4 + - name: checkout node + uses: actions/setup-node@v4 + with: + node-version: '18' + - run: npm install -g pnpm@latest + - run: pnpm install + - run: pnpm run build + - run: TZ=Europe/Zurich pnpm test -- --coverage + node20: + name: Node 20 + runs-on: ubuntu-22.04 + steps: + - name: checkout + uses: actions/checkout@v4 + - name: checkout node + uses: actions/setup-node@v4 + with: + node-version: '20' + - run: npm install -g pnpm@latest + - run: pnpm install + - run: pnpm run build + - run: TZ=Europe/Zurich pnpm test -- --coverage + - name: coveralls.io + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + - name: sonarcloud.io + uses: sonarsource/sonarcloud-github-action@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..97bee46 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +coverage diff --git a/README.md b/README.md new file mode 100644 index 0000000..9486174 --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +# solid-petstore + +[![CI](https://github.com/chubbyts/solid-petstore/workflows/CI/badge.svg?branch=master)](https://github.com/chubbyts/solid-petstore/actions?query=workflow%3ACI) +[![Coverage Status](https://coveralls.io/repos/github/chubbyts/solid-petstore/badge.svg?branch=master)](https://coveralls.io/github/chubbyts/solid-petstore?branch=master) + +[![bugs](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_solid-petstore&metric=bugs)](https://sonarcloud.io/dashboard?id=chubbyts_solid-petstore) +[![code_smells](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_solid-petstore&metric=code_smells)](https://sonarcloud.io/dashboard?id=chubbyts_solid-petstore) +[![coverage](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_solid-petstore&metric=coverage)](https://sonarcloud.io/dashboard?id=chubbyts_solid-petstore) +[![duplicated_lines_density](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_solid-petstore&metric=duplicated_lines_density)](https://sonarcloud.io/dashboard?id=chubbyts_solid-petstore) +[![ncloc](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_solid-petstore&metric=ncloc)](https://sonarcloud.io/dashboard?id=chubbyts_solid-petstore) +[![sqale_rating](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_solid-petstore&metric=sqale_rating)](https://sonarcloud.io/dashboard?id=chubbyts_solid-petstore) +[![alert_status](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_solid-petstore&metric=alert_status)](https://sonarcloud.io/dashboard?id=chubbyts_solid-petstore) +[![reliability_rating](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_solid-petstore&metric=reliability_rating)](https://sonarcloud.io/dashboard?id=chubbyts_solid-petstore) +[![security_rating](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_solid-petstore&metric=security_rating)](https://sonarcloud.io/dashboard?id=chubbyts_solid-petstore) +[![sqale_index](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_solid-petstore&metric=sqale_index)](https://sonarcloud.io/dashboard?id=chubbyts_solid-petstore) +[![vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=chubbyts_solid-petstore&metric=vulnerabilities)](https://sonarcloud.io/dashboard?id=chubbyts_solid-petstore) + +## Description + +This is a solidjs frontend for the petstore skeleton. + +## Scripts + +### Compiles and hot-reloads for development +``` +pnpm start +``` + +### Compiles and minifies for production +``` +pnpm build +``` + +### Run your unit tests +``` +pnpm test +``` + +## Copyright + +2024 Dominik Zogg diff --git a/index.html b/index.html new file mode 100644 index 0000000..7021737 --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + Solid + TS + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..6f447b8 --- /dev/null +++ b/package.json @@ -0,0 +1,66 @@ +{ + "name": "solid-petstore", + "type": "module", + "version": "1.0.0", + "description": "A skeleton solidjs app for the petstore api.", + "keywords": [ + "chubbyts", + "skleton", + "solid" + ], + "author": "Dominik Zogg", + "license": "MIT", + "repository": "chubbyts/solid-petstore", + "scripts": { + "build": "tsc && vite build", + "cs-fix": "prettier --write src tests", + "cs": "prettier --check src tests", + "develop": "vite", + "lint-fix": "eslint src tests --fix", + "lint": "eslint src tests", + "start": "pnpm i && pnpm cs-fix && pnpm develop", + "test": "vitest" + }, + "dependencies": { + "@chubbyts/chubbyts-throwable-to-error": "^1.2.1", + "@solidjs/router": "^0.12.4", + "autoprefixer": "^10.4.17", + "date-fns": "^3.3.1", + "i": "^0.3.7", + "postcss": "^8.4.35", + "qs": "^6.11.2", + "solid-js": "^1.8.15", + "tailwindcss": "^3.4.1", + "zod": "^3.22.4" + }, + "devDependencies": { + "@solidjs/testing-library": "^0.8.6", + "@testing-library/jest-dom": "^6.4.2", + "@testing-library/user-event": "^14.5.2", + "@types/node": "^20.11.20", + "@types/prettier": "^2.7.3", + "@types/qs": "^6.9.12", + "@typescript-eslint/eslint-plugin": "^7.1.0", + "@typescript-eslint/parser": "^7.1.0", + "@vitest/coverage-v8": "^1.3.1", + "cross-fetch": "^4.0.0", + "eslint": "^8.57.0", + "eslint-plugin-solid": "^0.13.1", + "fetch-mock": "^9.11.0", + "jsdom": "^24.0.0", + "prettier": "^2.8.8", + "typescript": "^5.2.2", + "vite": "^5.1.4", + "vite-plugin-solid": "^2.10.1", + "vitest": "^1.3.1" + }, + "engines": { + "node": ">=16" + }, + "prettier": { + "printWidth": 120, + "tabWidth": 2, + "singleQuote": true, + "trailingComma": "all" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..a57836c --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,3964 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + '@chubbyts/chubbyts-throwable-to-error': + specifier: ^1.2.1 + version: 1.2.1 + '@solidjs/router': + specifier: ^0.12.4 + version: 0.12.4(solid-js@1.8.15) + autoprefixer: + specifier: ^10.4.17 + version: 10.4.17(postcss@8.4.35) + date-fns: + specifier: ^3.3.1 + version: 3.3.1 + i: + specifier: ^0.3.7 + version: 0.3.7 + postcss: + specifier: ^8.4.35 + version: 8.4.35 + qs: + specifier: ^6.11.2 + version: 6.11.2 + solid-js: + specifier: ^1.8.15 + version: 1.8.15 + tailwindcss: + specifier: ^3.4.1 + version: 3.4.1 + zod: + specifier: ^3.22.4 + version: 3.22.4 + +devDependencies: + '@solidjs/testing-library': + specifier: ^0.8.6 + version: 0.8.6(@solidjs/router@0.12.4)(solid-js@1.8.15) + '@testing-library/jest-dom': + specifier: ^6.4.2 + version: 6.4.2(vitest@1.3.1) + '@testing-library/user-event': + specifier: ^14.5.2 + version: 14.5.2(@testing-library/dom@9.3.4) + '@types/node': + specifier: ^20.11.20 + version: 20.11.24 + '@types/prettier': + specifier: ^2.7.3 + version: 2.7.3 + '@types/qs': + specifier: ^6.9.12 + version: 6.9.12 + '@typescript-eslint/eslint-plugin': + specifier: ^7.1.0 + version: 7.1.0(@typescript-eslint/parser@7.1.0)(eslint@8.57.0)(typescript@5.3.3) + '@typescript-eslint/parser': + specifier: ^7.1.0 + version: 7.1.0(eslint@8.57.0)(typescript@5.3.3) + '@vitest/coverage-v8': + specifier: ^1.3.1 + version: 1.3.1(vitest@1.3.1) + cross-fetch: + specifier: ^4.0.0 + version: 4.0.0 + eslint: + specifier: ^8.57.0 + version: 8.57.0 + eslint-plugin-solid: + specifier: ^0.13.1 + version: 0.13.1(eslint@8.57.0)(typescript@5.3.3) + fetch-mock: + specifier: ^9.11.0 + version: 9.11.0 + jsdom: + specifier: ^24.0.0 + version: 24.0.0 + prettier: + specifier: ^2.8.8 + version: 2.8.8 + typescript: + specifier: ^5.2.2 + version: 5.3.3 + vite: + specifier: ^5.1.4 + version: 5.1.4(@types/node@20.11.24) + vite-plugin-solid: + specifier: ^2.10.1 + version: 2.10.1(@testing-library/jest-dom@6.4.2)(solid-js@1.8.15)(vite@5.1.4) + vitest: + specifier: ^1.3.1 + version: 1.3.1(@types/node@20.11.24)(jsdom@24.0.0) + +packages: + + /@aashutoshrathi/word-wrap@1.2.6: + resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} + engines: {node: '>=0.10.0'} + dev: true + + /@adobe/css-tools@4.3.3: + resolution: {integrity: sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==} + dev: true + + /@alloc/quick-lru@5.2.0: + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + dev: false + + /@ampproject/remapping@2.2.1: + resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.3.4 + '@jridgewell/trace-mapping': 0.3.23 + dev: true + + /@babel/code-frame@7.23.5: + resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.23.4 + chalk: 2.4.2 + dev: true + + /@babel/compat-data@7.23.5: + resolution: {integrity: sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/core@7.24.0: + resolution: {integrity: sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.23.5 + '@babel/generator': 7.23.6 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.0) + '@babel/helpers': 7.24.0 + '@babel/parser': 7.24.0 + '@babel/template': 7.24.0 + '@babel/traverse': 7.24.0 + '@babel/types': 7.24.0 + convert-source-map: 2.0.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/generator@7.23.6: + resolution: {integrity: sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.0 + '@jridgewell/gen-mapping': 0.3.4 + '@jridgewell/trace-mapping': 0.3.23 + jsesc: 2.5.2 + dev: true + + /@babel/helper-compilation-targets@7.23.6: + resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/compat-data': 7.23.5 + '@babel/helper-validator-option': 7.23.5 + browserslist: 4.23.0 + lru-cache: 5.1.1 + semver: 6.3.1 + dev: true + + /@babel/helper-environment-visitor@7.22.20: + resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-function-name@7.23.0: + resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.24.0 + '@babel/types': 7.24.0 + dev: true + + /@babel/helper-hoist-variables@7.22.5: + resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.0 + dev: true + + /@babel/helper-module-imports@7.18.6: + resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.0 + dev: true + + /@babel/helper-module-imports@7.22.15: + resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.0 + dev: true + + /@babel/helper-module-transforms@7.23.3(@babel/core@7.24.0): + resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.24.0 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.20 + dev: true + + /@babel/helper-plugin-utils@7.24.0: + resolution: {integrity: sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-simple-access@7.22.5: + resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.0 + dev: true + + /@babel/helper-split-export-declaration@7.22.6: + resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.0 + dev: true + + /@babel/helper-string-parser@7.23.4: + resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-identifier@7.22.20: + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-option@7.23.5: + resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helpers@7.24.0: + resolution: {integrity: sha512-ulDZdc0Aj5uLc5nETsa7EPx2L7rM0YJM8r7ck7U73AXi7qOV44IHHRAYZHY6iU1rr3C5N4NtTmMRUJP6kwCWeA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.24.0 + '@babel/traverse': 7.24.0 + '@babel/types': 7.24.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/highlight@7.23.4: + resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.22.20 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + + /@babel/parser@7.24.0: + resolution: {integrity: sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.24.0 + dev: true + + /@babel/plugin-syntax-jsx@7.23.3(@babel/core@7.24.0): + resolution: {integrity: sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.0 + '@babel/helper-plugin-utils': 7.24.0 + dev: true + + /@babel/runtime@7.24.0: + resolution: {integrity: sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.1 + dev: true + + /@babel/template@7.24.0: + resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.23.5 + '@babel/parser': 7.24.0 + '@babel/types': 7.24.0 + dev: true + + /@babel/traverse@7.24.0: + resolution: {integrity: sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.23.5 + '@babel/generator': 7.23.6 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/parser': 7.24.0 + '@babel/types': 7.24.0 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/types@7.24.0: + resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.23.4 + '@babel/helper-validator-identifier': 7.22.20 + to-fast-properties: 2.0.0 + dev: true + + /@bcoe/v8-coverage@0.2.3: + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + dev: true + + /@chubbyts/chubbyts-throwable-to-error@1.2.1: + resolution: {integrity: sha512-sqmz+niGqD2gujhK01//c3kQjhL3l0S+pBVWWGUORP1kgyjuevUBaMvP1pajv7gH3UwMoop5LyjakbRv5Berow==} + engines: {node: '>=16'} + dev: false + + /@esbuild/aix-ppc64@0.19.12: + resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64@0.19.12: + resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.19.12: + resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.19.12: + resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.19.12: + resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.19.12: + resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.19.12: + resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.19.12: + resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.19.12: + resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.19.12: + resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.19.12: + resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.19.12: + resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.19.12: + resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.19.12: + resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.19.12: + resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.19.12: + resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.19.12: + resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.19.12: + resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.19.12: + resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.19.12: + resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.19.12: + resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.19.12: + resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.19.12: + resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.57.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@eslint-community/regexpp@4.10.0: + resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true + + /@eslint/eslintrc@2.1.4: + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.6.1 + globals: 13.24.0 + ignore: 5.3.1 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@eslint/js@8.57.0: + resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@humanwhocodes/config-array@0.11.14: + resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 2.0.2 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + + /@humanwhocodes/object-schema@2.0.2: + resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} + dev: true + + /@isaacs/cliui@8.0.2: + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + dependencies: + string-width: 5.1.2 + string-width-cjs: /string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: /strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: /wrap-ansi@7.0.0 + dev: false + + /@istanbuljs/schema@0.1.3: + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + dev: true + + /@jest/schemas@29.6.3: + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@sinclair/typebox': 0.27.8 + dev: true + + /@jridgewell/gen-mapping@0.3.4: + resolution: {integrity: sha512-Oud2QPM5dHviZNn4y/WhhYKSXksv+1xLEIsNrAbGcFzUN3ubqWRFT5gwPchNc5NuzILOU4tPBDTZ4VwhL8Y7cw==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.23 + + /@jridgewell/resolve-uri@3.1.2: + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + /@jridgewell/set-array@1.2.1: + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + + /@jridgewell/trace-mapping@0.3.23: + resolution: {integrity: sha512-9/4foRoUKp8s96tSkh8DlAAc5A0Ty8vLXld+l9gjKKY6ckwI8G15f0hskGmuLZu78ZlGa1vtsfOa+lnB4vG6Jg==} + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + + /@pkgjs/parseargs@0.11.0: + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-android-arm-eabi@4.12.0: + resolution: {integrity: sha512-+ac02NL/2TCKRrJu2wffk1kZ+RyqxVUlbjSagNgPm94frxtr+XDL12E5Ll1enWskLrtrZ2r8L3wED1orIibV/w==} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-android-arm64@4.12.0: + resolution: {integrity: sha512-OBqcX2BMe6nvjQ0Nyp7cC90cnumt8PXmO7Dp3gfAju/6YwG0Tj74z1vKrfRz7qAv23nBcYM8BCbhrsWqO7PzQQ==} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-arm64@4.12.0: + resolution: {integrity: sha512-X64tZd8dRE/QTrBIEs63kaOBG0b5GVEd3ccoLtyf6IdXtHdh8h+I56C2yC3PtC9Ucnv0CpNFJLqKFVgCYe0lOQ==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-x64@4.12.0: + resolution: {integrity: sha512-cc71KUZoVbUJmGP2cOuiZ9HSOP14AzBAThn3OU+9LcA1+IUqswJyR1cAJj3Mg55HbjZP6OLAIscbQsQLrpgTOg==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm-gnueabihf@4.12.0: + resolution: {integrity: sha512-a6w/Y3hyyO6GlpKL2xJ4IOh/7d+APaqLYdMf86xnczU3nurFTaVN9s9jOXQg97BE4nYm/7Ga51rjec5nfRdrvA==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-gnu@4.12.0: + resolution: {integrity: sha512-0fZBq27b+D7Ar5CQMofVN8sggOVhEtzFUwOwPppQt0k+VR+7UHMZZY4y+64WJ06XOhBTKXtQB/Sv0NwQMXyNAA==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-musl@4.12.0: + resolution: {integrity: sha512-eTvzUS3hhhlgeAv6bfigekzWZjaEX9xP9HhxB0Dvrdbkk5w/b+1Sxct2ZuDxNJKzsRStSq1EaEkVSEe7A7ipgQ==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-riscv64-gnu@4.12.0: + resolution: {integrity: sha512-ix+qAB9qmrCRiaO71VFfY8rkiAZJL8zQRXveS27HS+pKdjwUfEhqo2+YF2oI+H/22Xsiski+qqwIBxVewLK7sw==} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-gnu@4.12.0: + resolution: {integrity: sha512-TenQhZVOtw/3qKOPa7d+QgkeM6xY0LtwzR8OplmyL5LrgTWIXpTQg2Q2ycBf8jm+SFW2Wt/DTn1gf7nFp3ssVA==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-musl@4.12.0: + resolution: {integrity: sha512-LfFdRhNnW0zdMvdCb5FNuWlls2WbbSridJvxOvYWgSBOYZtgBfW9UGNJG//rwMqTX1xQE9BAodvMH9tAusKDUw==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-arm64-msvc@4.12.0: + resolution: {integrity: sha512-JPDxovheWNp6d7AHCgsUlkuCKvtu3RB55iNEkaQcf0ttsDU/JZF+iQnYcQJSk/7PtT4mjjVG8N1kpwnI9SLYaw==} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-ia32-msvc@4.12.0: + resolution: {integrity: sha512-fjtuvMWRGJn1oZacG8IPnzIV6GF2/XG+h71FKn76OYFqySXInJtseAqdprVTDTyqPxQOG9Exak5/E9Z3+EJ8ZA==} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-x64-msvc@4.12.0: + resolution: {integrity: sha512-ZYmr5mS2wd4Dew/JjT0Fqi2NPB/ZhZ2VvPp7SmvPZb4Y1CG/LRcS6tcRo2cYU7zLK5A7cdbhWnnWmUjoI4qapg==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@sinclair/typebox@0.27.8: + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + dev: true + + /@solidjs/router@0.12.4(solid-js@1.8.15): + resolution: {integrity: sha512-2S5QWYmpWSIWn5ei85eoStEMmECERX2BiBkEvmqYDrgX79I8D95YaWVdHbcFGOxISPTY4TP7RxjRiofs/AIFJQ==} + peerDependencies: + solid-js: ^1.8.6 + dependencies: + solid-js: 1.8.15 + + /@solidjs/testing-library@0.8.6(@solidjs/router@0.12.4)(solid-js@1.8.15): + resolution: {integrity: sha512-MnDGfUw38SjE+lmCDZ44HeZq5WbDU7s/BTa7uvqv55GKatddoWiJmHanUAbuEtmwMdEv+fFQQzftkqrFXEn1BQ==} + engines: {node: '>= 14'} + peerDependencies: + '@solidjs/router': '>=0.9.0' + solid-js: '>=1.0.0' + dependencies: + '@solidjs/router': 0.12.4(solid-js@1.8.15) + '@testing-library/dom': 9.3.4 + solid-js: 1.8.15 + dev: true + + /@testing-library/dom@9.3.4: + resolution: {integrity: sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==} + engines: {node: '>=14'} + dependencies: + '@babel/code-frame': 7.23.5 + '@babel/runtime': 7.24.0 + '@types/aria-query': 5.0.4 + aria-query: 5.1.3 + chalk: 4.1.2 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + pretty-format: 27.5.1 + dev: true + + /@testing-library/jest-dom@6.4.2(vitest@1.3.1): + resolution: {integrity: sha512-CzqH0AFymEMG48CpzXFriYYkOjk6ZGPCLMhW9e9jg3KMCn5OfJecF8GtGW7yGfR/IgCe3SX8BSwjdzI6BBbZLw==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + peerDependencies: + '@jest/globals': '>= 28' + '@types/bun': latest + '@types/jest': '>= 28' + jest: '>= 28' + vitest: '>= 0.32' + peerDependenciesMeta: + '@jest/globals': + optional: true + '@types/bun': + optional: true + '@types/jest': + optional: true + jest: + optional: true + vitest: + optional: true + dependencies: + '@adobe/css-tools': 4.3.3 + '@babel/runtime': 7.24.0 + aria-query: 5.3.0 + chalk: 3.0.0 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + lodash: 4.17.21 + redent: 3.0.0 + vitest: 1.3.1(@types/node@20.11.24)(jsdom@24.0.0) + dev: true + + /@testing-library/user-event@14.5.2(@testing-library/dom@9.3.4): + resolution: {integrity: sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==} + engines: {node: '>=12', npm: '>=6'} + peerDependencies: + '@testing-library/dom': '>=7.21.4' + dependencies: + '@testing-library/dom': 9.3.4 + dev: true + + /@types/aria-query@5.0.4: + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + dev: true + + /@types/babel__core@7.20.5: + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + dependencies: + '@babel/parser': 7.24.0 + '@babel/types': 7.24.0 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.5 + dev: true + + /@types/babel__generator@7.6.8: + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + dependencies: + '@babel/types': 7.24.0 + dev: true + + /@types/babel__template@7.4.4: + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + dependencies: + '@babel/parser': 7.24.0 + '@babel/types': 7.24.0 + dev: true + + /@types/babel__traverse@7.20.5: + resolution: {integrity: sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==} + dependencies: + '@babel/types': 7.24.0 + dev: true + + /@types/estree@1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + dev: true + + /@types/istanbul-lib-coverage@2.0.6: + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + dev: true + + /@types/json-schema@7.0.15: + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + dev: true + + /@types/node@20.11.24: + resolution: {integrity: sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==} + dependencies: + undici-types: 5.26.5 + dev: true + + /@types/prettier@2.7.3: + resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} + dev: true + + /@types/qs@6.9.12: + resolution: {integrity: sha512-bZcOkJ6uWrL0Qb2NAWKa7TBU+mJHPzhx9jjLL1KHF+XpzEcR7EXHvjbHlGtR/IsP1vyPrehuS6XqkmaePy//mg==} + dev: true + + /@types/semver@7.5.8: + resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} + dev: true + + /@typescript-eslint/eslint-plugin@7.1.0(@typescript-eslint/parser@7.1.0)(eslint@8.57.0)(typescript@5.3.3): + resolution: {integrity: sha512-j6vT/kCulhG5wBmGtstKeiVr1rdXE4nk+DT1k6trYkwlrvW9eOF5ZbgKnd/YR6PcM4uTEXa0h6Fcvf6X7Dxl0w==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + '@typescript-eslint/parser': ^7.0.0 + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.10.0 + '@typescript-eslint/parser': 7.1.0(eslint@8.57.0)(typescript@5.3.3) + '@typescript-eslint/scope-manager': 7.1.0 + '@typescript-eslint/type-utils': 7.1.0(eslint@8.57.0)(typescript@5.3.3) + '@typescript-eslint/utils': 7.1.0(eslint@8.57.0)(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 7.1.0 + debug: 4.3.4 + eslint: 8.57.0 + graphemer: 1.4.0 + ignore: 5.3.1 + natural-compare: 1.4.0 + semver: 7.6.0 + ts-api-utils: 1.2.1(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.3.3): + resolution: {integrity: sha512-V1EknKUubZ1gWFjiOZhDSNToOjs63/9O0puCgGS8aDOgpZY326fzFu15QAUjwaXzRZjf/qdsdBrckYdv9YxB8w==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 7.1.0 + '@typescript-eslint/types': 7.1.0 + '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 7.1.0 + debug: 4.3.4 + eslint: 8.57.0 + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager@6.21.0: + resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 + dev: true + + /@typescript-eslint/scope-manager@7.1.0: + resolution: {integrity: sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 7.1.0 + '@typescript-eslint/visitor-keys': 7.1.0 + dev: true + + /@typescript-eslint/type-utils@7.1.0(eslint@8.57.0)(typescript@5.3.3): + resolution: {integrity: sha512-UZIhv8G+5b5skkcuhgvxYWHjk7FW7/JP5lPASMEUoliAPwIH/rxoUSQPia2cuOj9AmDZmwUl1usKm85t5VUMew==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.3.3) + '@typescript-eslint/utils': 7.1.0(eslint@8.57.0)(typescript@5.3.3) + debug: 4.3.4 + eslint: 8.57.0 + ts-api-utils: 1.2.1(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types@6.21.0: + resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} + engines: {node: ^16.0.0 || >=18.0.0} + dev: true + + /@typescript-eslint/types@7.1.0: + resolution: {integrity: sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==} + engines: {node: ^16.0.0 || >=18.0.0} + dev: true + + /@typescript-eslint/typescript-estree@6.21.0(typescript@5.3.3): + resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.3 + semver: 7.6.0 + ts-api-utils: 1.2.1(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/typescript-estree@7.1.0(typescript@5.3.3): + resolution: {integrity: sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 7.1.0 + '@typescript-eslint/visitor-keys': 7.1.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.3 + semver: 7.6.0 + ts-api-utils: 1.2.1(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils@6.21.0(eslint@8.57.0)(typescript@5.3.3): + resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.8 + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.3.3) + eslint: 8.57.0 + semver: 7.6.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/utils@7.1.0(eslint@8.57.0)(typescript@5.3.3): + resolution: {integrity: sha512-WUFba6PZC5OCGEmbweGpnNJytJiLG7ZvDBJJoUcX4qZYf1mGZ97mO2Mps6O2efxJcJdRNpqweCistDbZMwIVHw==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^8.56.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.8 + '@typescript-eslint/scope-manager': 7.1.0 + '@typescript-eslint/types': 7.1.0 + '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.3.3) + eslint: 8.57.0 + semver: 7.6.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys@6.21.0: + resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.21.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@typescript-eslint/visitor-keys@7.1.0: + resolution: {integrity: sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 7.1.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@ungap/structured-clone@1.2.0: + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + dev: true + + /@vitest/coverage-v8@1.3.1(vitest@1.3.1): + resolution: {integrity: sha512-UuBnkSJUNE9rdHjDCPyJ4fYuMkoMtnghes1XohYa4At0MS3OQSAo97FrbwSLRshYsXThMZy1+ybD/byK5llyIg==} + peerDependencies: + vitest: 1.3.1 + dependencies: + '@ampproject/remapping': 2.2.1 + '@bcoe/v8-coverage': 0.2.3 + debug: 4.3.4 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.7 + magic-string: 0.30.7 + magicast: 0.3.3 + picocolors: 1.0.0 + std-env: 3.7.0 + test-exclude: 6.0.0 + v8-to-istanbul: 9.2.0 + vitest: 1.3.1(@types/node@20.11.24)(jsdom@24.0.0) + transitivePeerDependencies: + - supports-color + dev: true + + /@vitest/expect@1.3.1: + resolution: {integrity: sha512-xofQFwIzfdmLLlHa6ag0dPV8YsnKOCP1KdAeVVh34vSjN2dcUiXYCD9htu/9eM7t8Xln4v03U9HLxLpPlsXdZw==} + dependencies: + '@vitest/spy': 1.3.1 + '@vitest/utils': 1.3.1 + chai: 4.4.1 + dev: true + + /@vitest/runner@1.3.1: + resolution: {integrity: sha512-5FzF9c3jG/z5bgCnjr8j9LNq/9OxV2uEBAITOXfoe3rdZJTdO7jzThth7FXv/6b+kdY65tpRQB7WaKhNZwX+Kg==} + dependencies: + '@vitest/utils': 1.3.1 + p-limit: 5.0.0 + pathe: 1.1.2 + dev: true + + /@vitest/snapshot@1.3.1: + resolution: {integrity: sha512-EF++BZbt6RZmOlE3SuTPu/NfwBF6q4ABS37HHXzs2LUVPBLx2QoY/K0fKpRChSo8eLiuxcbCVfqKgx/dplCDuQ==} + dependencies: + magic-string: 0.30.7 + pathe: 1.1.2 + pretty-format: 29.7.0 + dev: true + + /@vitest/spy@1.3.1: + resolution: {integrity: sha512-xAcW+S099ylC9VLU7eZfdT9myV67Nor9w9zhf0mGCYJSO+zM2839tOeROTdikOi/8Qeusffvxb/MyBSOja1Uig==} + dependencies: + tinyspy: 2.2.1 + dev: true + + /@vitest/utils@1.3.1: + resolution: {integrity: sha512-d3Waie/299qqRyHTm2DjADeTaNdNSVsnwHPWrs20JMpjh6eiVq7ggggweO8rc4arhf6rRkWuHKwvxGvejUXZZQ==} + dependencies: + diff-sequences: 29.6.3 + estree-walker: 3.0.3 + loupe: 2.3.7 + pretty-format: 29.7.0 + dev: true + + /acorn-jsx@5.3.2(acorn@8.11.3): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.11.3 + dev: true + + /acorn-walk@8.3.2: + resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} + engines: {node: '>=0.4.0'} + dev: true + + /acorn@8.11.3: + resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /agent-base@7.1.0: + resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} + engines: {node: '>= 14'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + /ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: false + + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + + /ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + dev: true + + /ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: false + + /any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + dev: false + + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: false + + /arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + dev: false + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /aria-query@5.1.3: + resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} + dependencies: + deep-equal: 2.2.3 + dev: true + + /aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + dependencies: + dequal: 2.0.3 + dev: true + + /array-buffer-byte-length@1.0.1: + resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + is-array-buffer: 3.0.4 + dev: true + + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /assertion-error@1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + dev: true + + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: true + + /autoprefixer@10.4.17(postcss@8.4.35): + resolution: {integrity: sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + dependencies: + browserslist: 4.23.0 + caniuse-lite: 1.0.30001591 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.0.0 + postcss: 8.4.35 + postcss-value-parser: 4.2.0 + dev: false + + /available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + dependencies: + possible-typed-array-names: 1.0.0 + dev: true + + /babel-plugin-jsx-dom-expressions@0.37.17(@babel/core@7.24.0): + resolution: {integrity: sha512-1bv8rOTzs6TR3DVyVZ7ElxyPEhnS556FMWRIsB3gBPfkn/cSKaLvXLGk+X1lvI+SzcUo4G+UcmJrn3vr1ig8mQ==} + peerDependencies: + '@babel/core': ^7.20.12 + dependencies: + '@babel/core': 7.24.0 + '@babel/helper-module-imports': 7.18.6 + '@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.24.0) + '@babel/types': 7.24.0 + html-entities: 2.3.3 + validate-html-nesting: 1.2.2 + dev: true + + /babel-preset-solid@1.8.15(@babel/core@7.24.0): + resolution: {integrity: sha512-P2yOQbB7Hn/m4YvpXV6ExHIMcgNWXWXcvY4kJzG3yqAB3hKS58OZRsvJ7RObsZWqXRvZTITBIwnpK0BMGu+ZIQ==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.24.0 + babel-plugin-jsx-dom-expressions: 0.37.17(@babel/core@7.24.0) + dev: true + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + /binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: false + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + + /browserslist@4.23.0: + resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001591 + electron-to-chromium: 1.4.687 + node-releases: 2.0.14 + update-browserslist-db: 1.0.13(browserslist@4.23.0) + + /cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + dev: true + + /call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + set-function-length: 1.2.1 + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + dev: false + + /caniuse-lite@1.0.30001591: + resolution: {integrity: sha512-PCzRMei/vXjJyL5mJtzNiUCKP59dm8Apqc3PH8gJkMnMXZGox93RbE76jHsmLwmIo6/3nsYIpJtx0O7u5PqFuQ==} + + /chai@4.4.1: + resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} + engines: {node: '>=4'} + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.3 + deep-eql: 4.1.3 + get-func-name: 2.0.2 + loupe: 2.3.7 + pathval: 1.1.1 + type-detect: 4.0.8 + dev: true + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk@3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /check-error@1.0.3: + resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + dependencies: + get-func-name: 2.0.2 + dev: true + + /chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + dev: false + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: true + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: true + + /commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + dev: false + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + dev: true + + /core-js@3.36.0: + resolution: {integrity: sha512-mt7+TUBbTFg5+GngsAxeKBTl5/VS0guFeJacYge9OmHb+m058UwwIm41SE9T4Den7ClatV57B6TYTuJ0CX1MAw==} + requiresBuild: true + dev: true + + /cross-fetch@4.0.0: + resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==} + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: true + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + /css.escape@1.5.1: + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + dev: true + + /cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /cssstyle@4.0.1: + resolution: {integrity: sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==} + engines: {node: '>=18'} + dependencies: + rrweb-cssom: 0.6.0 + dev: true + + /csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + /data-urls@5.0.0: + resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} + engines: {node: '>=18'} + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 14.0.0 + dev: true + + /date-fns@3.3.1: + resolution: {integrity: sha512-y8e109LYGgoQDveiEBD3DYXKba1jWf5BA8YU1FL5Tvm0BTdEfy54WLCwnuYWZNnzzvALy/QQ4Hov+Q9RVRv+Zw==} + dev: false + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /decimal.js@10.4.3: + resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} + dev: true + + /deep-eql@4.1.3: + resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} + engines: {node: '>=6'} + dependencies: + type-detect: 4.0.8 + dev: true + + /deep-equal@2.2.3: + resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.1 + call-bind: 1.0.7 + es-get-iterator: 1.1.3 + get-intrinsic: 1.2.4 + is-arguments: 1.1.1 + is-array-buffer: 3.0.4 + is-date-object: 1.0.5 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.3 + isarray: 2.0.5 + object-is: 1.1.6 + object-keys: 1.1.1 + object.assign: 4.1.5 + regexp.prototype.flags: 1.5.2 + side-channel: 1.0.5 + which-boxed-primitive: 1.0.2 + which-collection: 1.0.1 + which-typed-array: 1.1.14 + dev: true + + /deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + + /define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + dev: true + + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: true + + /dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + dev: true + + /didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + dev: false + + /diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: true + + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + dev: false + + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + dev: true + + /dom-accessibility-api@0.6.3: + resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} + dev: true + + /eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: false + + /electron-to-chromium@1.4.687: + resolution: {integrity: sha512-Ic85cOuXSP6h7KM0AIJ2hpJ98Bo4hyTUjc4yjMbkvD+8yTxEhfK9+8exT2KKYsSjnCn2tGsKVSZwE7ZgTORQCw==} + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: false + + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: false + + /entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + dev: true + + /es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.4 + + /es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + /es-get-iterator@1.1.3: + resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + has-symbols: 1.0.3 + is-arguments: 1.1.1 + is-map: 2.0.2 + is-set: 2.0.2 + is-string: 1.0.7 + isarray: 2.0.5 + stop-iteration-iterator: 1.0.0 + dev: true + + /esbuild@0.19.12: + resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.19.12 + '@esbuild/android-arm': 0.19.12 + '@esbuild/android-arm64': 0.19.12 + '@esbuild/android-x64': 0.19.12 + '@esbuild/darwin-arm64': 0.19.12 + '@esbuild/darwin-x64': 0.19.12 + '@esbuild/freebsd-arm64': 0.19.12 + '@esbuild/freebsd-x64': 0.19.12 + '@esbuild/linux-arm': 0.19.12 + '@esbuild/linux-arm64': 0.19.12 + '@esbuild/linux-ia32': 0.19.12 + '@esbuild/linux-loong64': 0.19.12 + '@esbuild/linux-mips64el': 0.19.12 + '@esbuild/linux-ppc64': 0.19.12 + '@esbuild/linux-riscv64': 0.19.12 + '@esbuild/linux-s390x': 0.19.12 + '@esbuild/linux-x64': 0.19.12 + '@esbuild/netbsd-x64': 0.19.12 + '@esbuild/openbsd-x64': 0.19.12 + '@esbuild/sunos-x64': 0.19.12 + '@esbuild/win32-arm64': 0.19.12 + '@esbuild/win32-ia32': 0.19.12 + '@esbuild/win32-x64': 0.19.12 + dev: true + + /escalade@3.1.2: + resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + engines: {node: '>=6'} + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: true + + /eslint-plugin-solid@0.13.1(eslint@8.57.0)(typescript@5.3.3): + resolution: {integrity: sha512-PdNrAylFzeh/SbnLc2pQ432l+bXFGzXj/qNqkh5QNVZCoWIdSs0CJA2D7hqW0DloztwUrzkVZCDWFWc3iRAm/Q==} + engines: {node: '>=12.0.0'} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.3.3) + eslint: 8.57.0 + is-html: 2.0.0 + kebab-case: 1.0.2 + known-css-properties: 0.24.0 + style-to-object: 0.3.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint@8.57.0: + resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/regexpp': 4.10.0 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.57.0 + '@humanwhocodes/config-array': 0.11.14 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.2.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.24.0 + graphemer: 1.4.0 + ignore: 5.3.1 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.3 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.11.3 + acorn-jsx: 5.3.2(acorn@8.11.3) + eslint-visitor-keys: 3.4.3 + dev: true + + /esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + dependencies: + '@types/estree': 1.0.5 + dev: true + + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + dev: true + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + dependencies: + reusify: 1.0.4 + + /fetch-mock@9.11.0: + resolution: {integrity: sha512-PG1XUv+x7iag5p/iNHD4/jdpxL9FtVSqRMUQhPab4hVDt80T1MH5ehzVrL2IdXO9Q2iBggArFvPqjUbHFuI58Q==} + engines: {node: '>=4.0.0'} + peerDependencies: + node-fetch: '*' + peerDependenciesMeta: + node-fetch: + optional: true + dependencies: + '@babel/core': 7.24.0 + '@babel/runtime': 7.24.0 + core-js: 3.36.0 + debug: 4.3.4 + glob-to-regexp: 0.4.1 + is-subset: 0.1.1 + lodash.isequal: 4.5.0 + path-to-regexp: 2.4.0 + querystring: 0.2.1 + whatwg-url: 6.5.0 + transitivePeerDependencies: + - supports-color + dev: true + + /file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.2.0 + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.3.1 + keyv: 4.5.4 + rimraf: 3.0.2 + dev: true + + /flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + dev: true + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: true + + /foreground-child@3.1.1: + resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} + engines: {node: '>=14'} + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + dev: false + + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: true + + /fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + dev: false + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + optional: true + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + /functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + + /gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: true + + /get-func-name@2.0.2: + resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + dev: true + + /get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.1 + + /get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + dev: true + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + + /glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + dev: true + + /glob@10.3.10: + resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + dependencies: + foreground-child: 3.1.1 + jackspeak: 2.3.6 + minimatch: 9.0.3 + minipass: 7.0.4 + path-scurry: 1.10.1 + dev: false + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: true + + /globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.1 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.4 + + /graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + dev: true + + /has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + dependencies: + es-define-property: 1.0.0 + + /has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + /has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /hasown@2.0.1: + resolution: {integrity: sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + + /html-encoding-sniffer@4.0.0: + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} + dependencies: + whatwg-encoding: 3.1.1 + dev: true + + /html-entities@2.3.3: + resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==} + dev: true + + /html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + dev: true + + /html-tags@3.3.1: + resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} + engines: {node: '>=8'} + dev: true + + /http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /https-proxy-agent@7.0.4: + resolution: {integrity: sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + dev: true + + /i@0.3.7: + resolution: {integrity: sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==} + engines: {node: '>=0.4'} + dev: false + + /iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: true + + /ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + dev: true + + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /inline-style-parser@0.1.1: + resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} + dev: true + + /internal-slot@1.0.7: + resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + hasown: 2.0.1 + side-channel: 1.0.5 + dev: true + + /is-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + dev: true + + /is-array-buffer@3.0.4: + resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + dev: true + + /is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: true + + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: false + + /is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + dev: true + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: true + + /is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + dependencies: + hasown: 2.0.1 + dev: false + + /is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: false + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + + /is-html@2.0.0: + resolution: {integrity: sha512-S+OpgB5i7wzIue/YSE5hg0e5ZYfG3hhpNh9KGl6ayJ38p7ED6wxQLd1TV91xHpcTvw90KMJ9EwN3F/iNflHBVg==} + engines: {node: '>=8'} + dependencies: + html-tags: 3.3.1 + dev: true + + /is-map@2.0.2: + resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} + dev: true + + /is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + + /is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + dev: true + + /is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + dev: true + + /is-set@2.0.2: + resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==} + dev: true + + /is-shared-array-buffer@1.0.3: + resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + dev: true + + /is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-subset@0.1.1: + resolution: {integrity: sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==} + dev: true + + /is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /is-weakmap@2.0.1: + resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==} + dev: true + + /is-weakset@2.0.2: + resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==} + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + dev: true + + /is-what@4.1.16: + resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} + engines: {node: '>=12.13'} + dev: true + + /isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + /istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + dev: true + + /istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + dev: true + + /istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + dependencies: + debug: 4.3.4 + istanbul-lib-coverage: 3.2.2 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + dev: true + + /jackspeak@2.3.6: + resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} + engines: {node: '>=14'} + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + dev: false + + /jiti@1.21.0: + resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} + hasBin: true + dev: false + + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true + + /js-tokens@8.0.3: + resolution: {integrity: sha512-UfJMcSJc+SEXEl9lH/VLHSZbThQyLpw1vLO1Lb+j4RWDvG3N2f7yj3PVQA3cmkTBNldJ9eFnM+xEXxHIXrYiJw==} + dev: true + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /jsdom@24.0.0: + resolution: {integrity: sha512-UDS2NayCvmXSXVP6mpTj+73JnNQadZlr9N68189xib2tx5Mls7swlTNao26IoHv46BZJFvXygyRtyXd1feAk1A==} + engines: {node: '>=18'} + peerDependencies: + canvas: ^2.11.2 + peerDependenciesMeta: + canvas: + optional: true + dependencies: + cssstyle: 4.0.1 + data-urls: 5.0.0 + decimal.js: 10.4.3 + form-data: 4.0.0 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.4 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.7 + parse5: 7.1.2 + rrweb-cssom: 0.6.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 4.1.3 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.0.0 + ws: 8.16.0 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + dev: true + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: true + + /jsonc-parser@3.2.1: + resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==} + dev: true + + /kebab-case@1.0.2: + resolution: {integrity: sha512-7n6wXq4gNgBELfDCpzKc+mRrZFs7D+wgfF5WRFLNAr4DA/qtr9Js8uOAVAfHhuLMfAcQ0pRKqbpjx+TcJVdE1Q==} + dev: true + + /keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + dependencies: + json-buffer: 3.0.1 + dev: true + + /known-css-properties@0.24.0: + resolution: {integrity: sha512-RTSoaUAfLvpR357vWzAz/50Q/BmHfmE6ETSWfutT0AJiw10e6CmcdYRQJlLRd95B53D0Y2aD1jSxD3V3ySF+PA==} + dev: true + + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + dev: false + + /lilconfig@3.1.1: + resolution: {integrity: sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==} + engines: {node: '>=14'} + dev: false + + /lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: false + + /local-pkg@0.5.0: + resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} + engines: {node: '>=14'} + dependencies: + mlly: 1.6.1 + pkg-types: 1.0.3 + dev: true + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + + /lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + dev: true + + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lodash.sortby@4.7.0: + resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} + dev: true + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: true + + /loupe@2.3.7: + resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + dependencies: + get-func-name: 2.0.2 + dev: true + + /lru-cache@10.2.0: + resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} + engines: {node: 14 || >=16.14} + dev: false + + /lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + dependencies: + yallist: 3.1.1 + dev: true + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + + /lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + dev: true + + /magic-string@0.30.7: + resolution: {integrity: sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /magicast@0.3.3: + resolution: {integrity: sha512-ZbrP1Qxnpoes8sz47AM0z08U+jW6TyRgZzcWy3Ma3vDhJttwMwAFDMMQFobwdBxByBD46JYmxRzeF7w2+wJEuw==} + dependencies: + '@babel/parser': 7.24.0 + '@babel/types': 7.24.0 + source-map-js: 1.0.2 + dev: true + + /make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + dependencies: + semver: 7.6.0 + dev: true + + /merge-anything@5.1.7: + resolution: {integrity: sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ==} + engines: {node: '>=12.13'} + dependencies: + is-what: 4.1.16 + dev: true + + /merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: true + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: true + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: true + + /mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + dev: true + + /min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + dev: true + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + + /minipass@7.0.4: + resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} + engines: {node: '>=16 || 14 >=14.17'} + dev: false + + /mlly@1.6.1: + resolution: {integrity: sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==} + dependencies: + acorn: 8.11.3 + pathe: 1.1.2 + pkg-types: 1.0.3 + ufo: 1.4.0 + dev: true + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true + + /mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + dev: false + + /nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: true + + /node-releases@2.0.14: + resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: false + + /normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + dev: false + + /npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + path-key: 4.0.0 + dev: true + + /nwsapi@2.2.7: + resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} + dev: true + + /object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: false + + /object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + dev: false + + /object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + + /object-is@1.1.6: + resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + dev: true + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object.assign@4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: true + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + dependencies: + mimic-fn: 4.0.0 + dev: true + + /optionator@0.9.3: + resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + engines: {node: '>= 0.8.0'} + dependencies: + '@aashutoshrathi/word-wrap': 1.2.6 + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-limit@5.0.0: + resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} + engines: {node: '>=18'} + dependencies: + yocto-queue: 1.0.0 + dev: true + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /parse5@7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + dependencies: + entities: 4.5.0 + dev: true + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + /path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + dev: true + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: false + + /path-scurry@1.10.1: + resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + lru-cache: 10.2.0 + minipass: 7.0.4 + dev: false + + /path-to-regexp@2.4.0: + resolution: {integrity: sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w==} + dev: true + + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + dev: true + + /pathval@1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + dev: true + + /picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + /pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + dev: false + + /pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + dev: false + + /pkg-types@1.0.3: + resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} + dependencies: + jsonc-parser: 3.2.1 + mlly: 1.6.1 + pathe: 1.1.2 + dev: true + + /possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + dev: true + + /postcss-import@15.1.0(postcss@8.4.35): + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + dependencies: + postcss: 8.4.35 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.8 + dev: false + + /postcss-js@4.0.1(postcss@8.4.35): + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + dependencies: + camelcase-css: 2.0.1 + postcss: 8.4.35 + dev: false + + /postcss-load-config@4.0.2(postcss@8.4.35): + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + dependencies: + lilconfig: 3.1.1 + postcss: 8.4.35 + yaml: 2.4.0 + dev: false + + /postcss-nested@6.0.1(postcss@8.4.35): + resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + dependencies: + postcss: 8.4.35 + postcss-selector-parser: 6.0.15 + dev: false + + /postcss-selector-parser@6.0.15: + resolution: {integrity: sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: false + + /postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + dev: false + + /postcss@8.4.35: + resolution: {integrity: sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.0 + source-map-js: 1.0.2 + + /prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + dev: true + + /pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + dev: true + + /pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.2.0 + dev: true + + /psl@1.9.0: + resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} + dev: true + + /punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + dev: true + + /qs@6.11.2: + resolution: {integrity: sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.5 + dev: false + + /querystring@0.2.1: + resolution: {integrity: sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==} + engines: {node: '>=0.4.x'} + deprecated: The querystring API is considered Legacy. new code should use the URLSearchParams API instead. + dev: true + + /querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + dev: true + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + /react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + dev: true + + /react-is@18.2.0: + resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + dev: true + + /read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + dependencies: + pify: 2.3.0 + dev: false + + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: false + + /redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + dev: true + + /regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + dev: true + + /regexp.prototype.flags@1.5.2: + resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-errors: 1.3.0 + set-function-name: 2.0.2 + dev: true + + /requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + dev: true + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: false + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /rollup@4.12.0: + resolution: {integrity: sha512-wz66wn4t1OHIJw3+XU7mJJQV/2NAfw5OAk6G6Hoo3zcvz/XOfQ52Vgi+AN4Uxoxi0KBBwk2g8zPrTDA4btSB/Q==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.12.0 + '@rollup/rollup-android-arm64': 4.12.0 + '@rollup/rollup-darwin-arm64': 4.12.0 + '@rollup/rollup-darwin-x64': 4.12.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.12.0 + '@rollup/rollup-linux-arm64-gnu': 4.12.0 + '@rollup/rollup-linux-arm64-musl': 4.12.0 + '@rollup/rollup-linux-riscv64-gnu': 4.12.0 + '@rollup/rollup-linux-x64-gnu': 4.12.0 + '@rollup/rollup-linux-x64-musl': 4.12.0 + '@rollup/rollup-win32-arm64-msvc': 4.12.0 + '@rollup/rollup-win32-ia32-msvc': 4.12.0 + '@rollup/rollup-win32-x64-msvc': 4.12.0 + fsevents: 2.3.3 + dev: true + + /rrweb-cssom@0.6.0: + resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: true + + /saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + dependencies: + xmlchars: 2.2.0 + dev: true + + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + dev: true + + /semver@7.6.0: + resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /seroval-plugins@1.0.4(seroval@1.0.4): + resolution: {integrity: sha512-DQ2IK6oQVvy8k+c2V5x5YCtUa/GGGsUwUBNN9UqohrZ0rWdUapBFpNMYP1bCyRHoxOJjdKGl+dieacFIpU/i1A==} + engines: {node: '>=10'} + peerDependencies: + seroval: ^1.0 + dependencies: + seroval: 1.0.4 + + /seroval@1.0.4: + resolution: {integrity: sha512-qQs/N+KfJu83rmszFQaTxcoJoPn6KNUruX4KmnmyD0oZkUoiNvJ1rpdYKDf4YHM05k+HOgCxa3yvf15QbVijGg==} + engines: {node: '>=10'} + + /set-function-length@1.2.1: + resolution: {integrity: sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + + /set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + dev: true + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + /side-channel@1.0.5: + resolution: {integrity: sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + object-inspect: 1.13.1 + + /siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + dev: true + + /signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /solid-js@1.8.15: + resolution: {integrity: sha512-d0QP/efr3UVcwGgWVPveQQ0IHOH6iU7yUhc2piy8arNG8wxKmvUy1kFxyF8owpmfCWGB87usDKMaVnsNYZm+Vw==} + dependencies: + csstype: 3.1.3 + seroval: 1.0.4 + seroval-plugins: 1.0.4(seroval@1.0.4) + + /solid-refresh@0.6.3(solid-js@1.8.15): + resolution: {integrity: sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA==} + peerDependencies: + solid-js: ^1.3 + dependencies: + '@babel/generator': 7.23.6 + '@babel/helper-module-imports': 7.22.15 + '@babel/types': 7.24.0 + solid-js: 1.8.15 + dev: true + + /source-map-js@1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + dev: true + + /std-env@3.7.0: + resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} + dev: true + + /stop-iteration-iterator@1.0.0: + resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} + engines: {node: '>= 0.4'} + dependencies: + internal-slot: 1.0.7 + dev: true + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: false + + /string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + dev: false + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + + /strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.0.1 + dev: false + + /strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + dev: true + + /strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + dependencies: + min-indent: 1.0.1 + dev: true + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /strip-literal@2.0.0: + resolution: {integrity: sha512-f9vHgsCWBq2ugHAkGMiiYY+AYG0D/cbloKKg0nhaaaSNsujdGIpVXCNsrJpCKr5M0f4aI31mr13UjY6GAuXCKA==} + dependencies: + js-tokens: 8.0.3 + dev: true + + /style-to-object@0.3.0: + resolution: {integrity: sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==} + dependencies: + inline-style-parser: 0.1.1 + dev: true + + /sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + dependencies: + '@jridgewell/gen-mapping': 0.3.4 + commander: 4.1.1 + glob: 10.3.10 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.6 + ts-interface-checker: 0.1.13 + dev: false + + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: false + + /symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + dev: true + + /tailwindcss@3.4.1: + resolution: {integrity: sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==} + engines: {node: '>=14.0.0'} + hasBin: true + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.6.0 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.2 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.0 + lilconfig: 2.1.0 + micromatch: 4.0.5 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.0.0 + postcss: 8.4.35 + postcss-import: 15.1.0(postcss@8.4.35) + postcss-js: 4.0.1(postcss@8.4.35) + postcss-load-config: 4.0.2(postcss@8.4.35) + postcss-nested: 6.0.1(postcss@8.4.35) + postcss-selector-parser: 6.0.15 + resolve: 1.22.8 + sucrase: 3.35.0 + transitivePeerDependencies: + - ts-node + dev: false + + /test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + dev: true + + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + dependencies: + thenify: 3.3.1 + dev: false + + /thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + dependencies: + any-promise: 1.3.0 + dev: false + + /tinybench@2.6.0: + resolution: {integrity: sha512-N8hW3PG/3aOoZAN5V/NSAEDz0ZixDSSt5b/a05iqtpgfLWMSVuCo7w0k2vVvEjdrIoeGqZzweX2WlyioNIHchA==} + dev: true + + /tinypool@0.8.2: + resolution: {integrity: sha512-SUszKYe5wgsxnNOVlBYO6IC+8VGWdVGZWAqUxp3UErNBtptZvWbwyUOyzNL59zigz2rCA92QiL3wvG+JDSdJdQ==} + engines: {node: '>=14.0.0'} + dev: true + + /tinyspy@2.2.1: + resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} + engines: {node: '>=14.0.0'} + dev: true + + /to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + dev: true + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + + /tough-cookie@4.1.3: + resolution: {integrity: sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==} + engines: {node: '>=6'} + dependencies: + psl: 1.9.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + dev: true + + /tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: true + + /tr46@1.0.1: + resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + dependencies: + punycode: 2.3.1 + dev: true + + /tr46@5.0.0: + resolution: {integrity: sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==} + engines: {node: '>=18'} + dependencies: + punycode: 2.3.1 + dev: true + + /ts-api-utils@1.2.1(typescript@5.3.3): + resolution: {integrity: sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' + dependencies: + typescript: 5.3.3 + dev: true + + /ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + dev: false + + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + dev: true + + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /typescript@5.3.3: + resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} + engines: {node: '>=14.17'} + hasBin: true + dev: true + + /ufo@1.4.0: + resolution: {integrity: sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==} + dev: true + + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: true + + /universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + dev: true + + /update-browserslist-db@1.0.13(browserslist@4.23.0): + resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.23.0 + escalade: 3.1.2 + picocolors: 1.0.0 + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.1 + dev: true + + /url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + dev: true + + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: false + + /v8-to-istanbul@9.2.0: + resolution: {integrity: sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==} + engines: {node: '>=10.12.0'} + dependencies: + '@jridgewell/trace-mapping': 0.3.23 + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 2.0.0 + dev: true + + /validate-html-nesting@1.2.2: + resolution: {integrity: sha512-hGdgQozCsQJMyfK5urgFcWEqsSSrK63Awe0t/IMR0bZ0QMtnuaiHzThW81guu3qx9abLi99NEuiaN6P9gVYsNg==} + dev: true + + /vite-node@1.3.1(@types/node@20.11.24): + resolution: {integrity: sha512-azbRrqRxlWTJEVbzInZCTchx0X69M/XPTCz4H+TLvlTcR/xH/3hkRqhOakT41fMJCMzXTu4UvegkZiEoJAWvng==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + dependencies: + cac: 6.7.14 + debug: 4.3.4 + pathe: 1.1.2 + picocolors: 1.0.0 + vite: 5.1.4(@types/node@20.11.24) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + + /vite-plugin-solid@2.10.1(@testing-library/jest-dom@6.4.2)(solid-js@1.8.15)(vite@5.1.4): + resolution: {integrity: sha512-kfVdNLWaJqaJVL52U6iCCKNW/nXE7bS1VVGOWPGllOkJfcNILymVSY0LCBLSnyy0iYnRtrXpiHm14rMuzeC7CA==} + peerDependencies: + '@testing-library/jest-dom': ^5.16.6 || ^5.17.0 || ^6.* + solid-js: ^1.7.2 + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + '@testing-library/jest-dom': + optional: true + dependencies: + '@babel/core': 7.24.0 + '@testing-library/jest-dom': 6.4.2(vitest@1.3.1) + '@types/babel__core': 7.20.5 + babel-preset-solid: 1.8.15(@babel/core@7.24.0) + merge-anything: 5.1.7 + solid-js: 1.8.15 + solid-refresh: 0.6.3(solid-js@1.8.15) + vite: 5.1.4(@types/node@20.11.24) + vitefu: 0.2.5(vite@5.1.4) + transitivePeerDependencies: + - supports-color + dev: true + + /vite@5.1.4(@types/node@20.11.24): + resolution: {integrity: sha512-n+MPqzq+d9nMVTKyewqw6kSt+R3CkvF9QAKY8obiQn8g1fwTscKxyfaYnC632HtBXAQGc1Yjomphwn1dtwGAHg==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 20.11.24 + esbuild: 0.19.12 + postcss: 8.4.35 + rollup: 4.12.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /vitefu@0.2.5(vite@5.1.4): + resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + vite: + optional: true + dependencies: + vite: 5.1.4(@types/node@20.11.24) + dev: true + + /vitest@1.3.1(@types/node@20.11.24)(jsdom@24.0.0): + resolution: {integrity: sha512-/1QJqXs8YbCrfv/GPQ05wAZf2eakUPLPa18vkJAKE7RXOKfVHqMZZ1WlTjiwl6Gcn65M5vpNUB6EFLnEdRdEXQ==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 1.3.1 + '@vitest/ui': 1.3.1 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + dependencies: + '@types/node': 20.11.24 + '@vitest/expect': 1.3.1 + '@vitest/runner': 1.3.1 + '@vitest/snapshot': 1.3.1 + '@vitest/spy': 1.3.1 + '@vitest/utils': 1.3.1 + acorn-walk: 8.3.2 + chai: 4.4.1 + debug: 4.3.4 + execa: 8.0.1 + jsdom: 24.0.0 + local-pkg: 0.5.0 + magic-string: 0.30.7 + pathe: 1.1.2 + picocolors: 1.0.0 + std-env: 3.7.0 + strip-literal: 2.0.0 + tinybench: 2.6.0 + tinypool: 0.8.2 + vite: 5.1.4(@types/node@20.11.24) + vite-node: 1.3.1(@types/node@20.11.24) + why-is-node-running: 2.2.2 + transitivePeerDependencies: + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + + /w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + dependencies: + xml-name-validator: 5.0.0 + dev: true + + /webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: true + + /webidl-conversions@4.0.2: + resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} + dev: true + + /webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + dev: true + + /whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + dependencies: + iconv-lite: 0.6.3 + dev: true + + /whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + dev: true + + /whatwg-url@14.0.0: + resolution: {integrity: sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==} + engines: {node: '>=18'} + dependencies: + tr46: 5.0.0 + webidl-conversions: 7.0.0 + dev: true + + /whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: true + + /whatwg-url@6.5.0: + resolution: {integrity: sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==} + dependencies: + lodash.sortby: 4.7.0 + tr46: 1.0.1 + webidl-conversions: 4.0.2 + dev: true + + /which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + + /which-collection@1.0.1: + resolution: {integrity: sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==} + dependencies: + is-map: 2.0.2 + is-set: 2.0.2 + is-weakmap: 2.0.1 + is-weakset: 2.0.2 + dev: true + + /which-typed-array@1.1.14: + resolution: {integrity: sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.2 + dev: true + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + + /why-is-node-running@2.2.2: + resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} + engines: {node: '>=8'} + hasBin: true + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + dev: true + + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: false + + /wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + dev: false + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /ws@8.16.0: + resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: true + + /xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + dev: true + + /xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + dev: true + + /yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + dev: true + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true + + /yaml@2.4.0: + resolution: {integrity: sha512-j9iR8g+/t0lArF4V6NE/QCfT+CO7iLqrXAHZbJdo+LfjqP1vR8Fg5bSiaq6Q2lOD1AUEVrEVIgABvBFYojJVYQ==} + engines: {node: '>= 14'} + hasBin: true + dev: false + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true + + /yocto-queue@1.0.0: + resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + engines: {node: '>=12.20'} + dev: true + + /zod@3.22.4: + resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} + dev: false diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..87e6b37 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,7 @@ +export default { + plugins: { + 'tailwindcss/nesting': {}, + tailwindcss: {}, + autoprefixer: {}, + } +}; diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..47d813d --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,10 @@ +sonar.organization=chubbyts +sonar.projectKey=chubbyts_solid-petstore +sonar.projectName=solid-petstore + +sonar.sources=src +sonar.exclusions=tests/** +sonar.tests=tests +sonar.language=typescript +sonar.sourceEncoding=UTF-8 +sonar.javascript.lcov.reportPaths=coverage/lcov.info diff --git a/src/api-client/error.ts b/src/api-client/error.ts new file mode 100644 index 0000000..d788ba2 --- /dev/null +++ b/src/api-client/error.ts @@ -0,0 +1,44 @@ +export class HttpError { + title: string; + detail?: string; + instance?: string; + constructor({ title, detail, instance }: { title: string; detail?: string; instance?: string }) { + this.title = title; + this.detail = detail; + this.instance = instance; + } +} + +export interface InvalidParameter { + name: string; + reason: string; + details?: { [key: string]: unknown }; +} + +export class BadRequestOrUnprocessableEntity extends HttpError { + invalidParameters?: Array; + constructor({ + title, + detail, + instance, + invalidParameters, + }: { + title: string; + detail?: string; + instance?: string; + invalidParameters?: Array; + }) { + super({ title, detail, instance }); + this.invalidParameters = invalidParameters; + } +} + +export class BadRequest extends BadRequestOrUnprocessableEntity {} + +export class InternalServerError extends HttpError {} + +export class NetworkError extends HttpError {} + +export class NotFound extends HttpError {} + +export class UnprocessableEntity extends BadRequestOrUnprocessableEntity {} diff --git a/src/api-client/pet.ts b/src/api-client/pet.ts new file mode 100644 index 0000000..68d5881 --- /dev/null +++ b/src/api-client/pet.ts @@ -0,0 +1,166 @@ +import { PetList, petListSchema, PetRequest, PetResponse, petResponseSchema } from '../model/model'; +import { throwableToError } from '@chubbyts/chubbyts-throwable-to-error/dist/throwable-to-error'; +import { BadRequest, HttpError, InternalServerError, NetworkError, NotFound, UnprocessableEntity } from './error'; + +const url = `${import.meta.env.VITE_PETSTORE_URL}/api/pets`; + +export const ListPets = async (queryString: string): Promise => { + try { + const response: Response = await fetch(`${url}?${queryString}`, { + method: 'GET', + headers: { + Accept: 'application/json', + }, + }); + + const json = await response.json(); + + if (200 === response.status) { + return petListSchema.parse(json); + } + + if (400 === response.status) { + return new BadRequest({ ...json }); + } + + if (500 === response.status) { + return new InternalServerError({ ...json }); + } + } catch (error) { + return new NetworkError({ title: throwableToError(error).message }); + } + + throw new Error('Unknown response'); +}; + +export const CreatePet = async (pet: PetRequest): Promise => { + try { + const response: Response = await fetch(url, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify(pet), + }); + + const json = await response.json(); + + if (201 === response.status) { + return petResponseSchema.parse(json); + } + + if (400 === response.status) { + return new BadRequest({ ...json }); + } + + if (422 === response.status) { + return new UnprocessableEntity({ ...json }); + } + + if (500 === response.status) { + return new InternalServerError({ ...json }); + } + } catch (error) { + return new NetworkError({ title: throwableToError(error).message }); + } + + throw new Error('Unknown response'); +}; + +export const ReadPet = async (id: string): Promise => { + try { + const response: Response = await fetch(`${url}/${id}`, { + method: 'GET', + headers: { + Accept: 'application/json', + }, + }); + + const json = await response.json(); + + if (200 === response.status) { + return petResponseSchema.parse(json); + } + + if (404 === response.status) { + return new NotFound({ ...json }); + } + + if (500 === response.status) { + return new InternalServerError({ ...json }); + } + } catch (error) { + return new NetworkError({ title: throwableToError(error).message }); + } + + throw new Error('Unknown response'); +}; + +export const UpdatePet = async (id: string, pet: PetRequest): Promise => { + try { + const response: Response = await fetch(`${url}/${id}`, { + method: 'PUT', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify(pet), + }); + + const json = await response.json(); + + if (200 === response.status) { + return petResponseSchema.parse(json); + } + + if (400 === response.status) { + return new BadRequest({ ...json }); + } + + if (404 === response.status) { + return new NotFound({ ...json }); + } + + if (422 === response.status) { + return new UnprocessableEntity({ ...json }); + } + + if (500 === response.status) { + return new InternalServerError({ ...json }); + } + } catch (error) { + return new NetworkError({ title: throwableToError(error).message }); + } + + throw new Error('Unknown response'); +}; + +export const DeletePet = async (id: string): Promise => { + try { + const response: Response = await fetch(`${url}/${id}`, { + method: 'DELETE', + headers: { + Accept: 'application/json', + }, + }); + + if (204 === response.status) { + return; + } + + const json = await response.json(); + + if (404 === response.status) { + return new NotFound({ ...json }); + } + + if (500 === response.status) { + return new InternalServerError({ ...json }); + } + } catch (error) { + return new NetworkError({ title: throwableToError(error).message }); + } + + throw new Error('Unknown response'); +}; diff --git a/src/app.tsx b/src/app.tsx new file mode 100644 index 0000000..ab43f3a --- /dev/null +++ b/src/app.tsx @@ -0,0 +1,46 @@ +import { Component, createSignal } from 'solid-js'; +import { A, RouteSectionProps } from '@solidjs/router'; + +const App: Component = (props: RouteSectionProps) => { + const [getDisplayMenu, setDisplayMenu] = createSignal(false); + + return ( +
+ + +
+ {props.children} +
+
+ ); +}; + +export default App; diff --git a/src/component/button.tsx b/src/component/button.tsx new file mode 100644 index 0000000..ec634b2 --- /dev/null +++ b/src/component/button.tsx @@ -0,0 +1,47 @@ +import { Component, JSX } from 'solid-js'; +import { A, AnchorProps } from '@solidjs/router'; + +type ColorTheme = 'blue' | 'gray' | 'green' | 'red'; + +const getColorThemeClasses = (colorTheme: ColorTheme) => { + switch (colorTheme) { + case 'blue': + return 'bg-blue-600 hover:bg-blue-700'; + case 'gray': + return 'bg-gray-600 hover:bg-gray-700'; + case 'green': + return 'bg-green-600 hover:bg-green-700'; + case 'red': + return 'bg-red-600 hover:bg-red-700'; + } +}; + +export const AnchorButton: Component = ( + props: AnchorProps & { colorTheme: ColorTheme }, +) => { + return ( + + {props.children} + + ); +}; + +export const Button: Component & { colorTheme: ColorTheme }> = ( + props: JSX.ButtonHTMLAttributes & { colorTheme: ColorTheme }, +) => { + return ( + + ); +}; diff --git a/src/component/form/form.tsx b/src/component/form/form.tsx new file mode 100644 index 0000000..77d18bc --- /dev/null +++ b/src/component/form/form.tsx @@ -0,0 +1,49 @@ +import { InvalidParameter } from '../../api-client/error'; +import { Component, For, JSX, Show } from 'solid-js'; + +type FieldsetProps = { + children: JSX.Element | string; +}; + +export const FieldSet: Component = (props: FieldsetProps) => { + return
{props.children}
; +}; + +export type TextFieldProps = { + label: string; + getValue: () => string; + setValue: (value: string) => void; + getInvalidParametersOrUndefined: () => Array | undefined; + testId?: string; +}; + +export const TextField: Component = (props: TextFieldProps) => { + return ( +
+ + props.setValue(event.currentTarget.value)} + onKeyPress={(event) => { + if (event.code !== 'Enter') { + return; + } + + props.setValue(event.currentTarget.value); + }} + value={props.getValue()} + /> + + {(getInvalidParameters) => ( +
    + {(invalidParameter) =>
  • {invalidParameter.reason}
  • }
    +
+ )} +
+
+ ); +}; diff --git a/src/component/form/pet-filters-form.tsx b/src/component/form/pet-filters-form.tsx new file mode 100644 index 0000000..a81555a --- /dev/null +++ b/src/component/form/pet-filters-form.tsx @@ -0,0 +1,63 @@ +import InvalidParameterByNameDenormalizer from '../../denormalizer/invalid-parameter-by-name-denormalizer'; +import { PetFilters } from '../../model/model'; +import { BadRequest } from '../../api-client/error'; +import { Component, createEffect } from 'solid-js'; +import { createStore } from 'solid-js/store'; +import { FieldSet, TextField } from './form'; +import { Button } from '../button'; + +const prefix = 'filters'; + +export type PetFiltersFormProps = { + getBadRequest: () => BadRequest | undefined; + getDefaultPetFilters: () => PetFilters; + submitPetFilters: (petFilters: PetFilters) => void; +}; + +export const PetFiltersForm: Component = (props: PetFiltersFormProps) => { + const getInvalidParameterByNameDenormalized = () => + InvalidParameterByNameDenormalizer(props.getBadRequest()?.invalidParameters ?? []); + + const [petFilters, setPetFilters] = createStore({}); + + const onSubmit = () => { + props.submitPetFilters({ ...petFilters }); + }; + + createEffect(() => { + setPetFilters(props.getDefaultPetFilters()); + }); + + return ( +
{ + e.preventDefault(); + e.stopPropagation(); + onSubmit(); + }} + > +
+ petFilters.name ?? ''} + setValue={(value) => { + console.log(value); + setPetFilters('name', value === '' ? undefined : value); + }} + getInvalidParametersOrUndefined={() => { + const invalidParameterByNameDenormalized = getInvalidParameterByNameDenormalized(); + + return ( + invalidParameterByNameDenormalized.get(`${prefix}[name]`) ?? + invalidParameterByNameDenormalized.get(`${prefix}.name`) + ); + }} + testId="pet-filter-input-name" + /> + +
+
+ ); +}; diff --git a/src/component/form/pet-form.tsx b/src/component/form/pet-form.tsx new file mode 100644 index 0000000..eec0efd --- /dev/null +++ b/src/component/form/pet-form.tsx @@ -0,0 +1,114 @@ +import InvalidParameterByNameDenormalizer from '../../denormalizer/invalid-parameter-by-name-denormalizer'; +import { PetRequest } from '../../model/model'; +import { BadRequestOrUnprocessableEntity } from '../../api-client/error'; +import { Component, For, createEffect } from 'solid-js'; +import { createStore } from 'solid-js/store'; +import { FieldSet, TextField } from './form'; +import { Button } from '../button'; + +export type PetFormProps = { + getBadRequestOrUnprocessableEntity: () => BadRequestOrUnprocessableEntity | undefined; + getDefaultPet?: () => PetRequest | undefined; + submitPet: (pet: PetRequest) => void; +}; + +export const PetForm: Component = (props: PetFormProps) => { + const getInvalidParameterByNameDenormalized = () => + InvalidParameterByNameDenormalizer(props.getBadRequestOrUnprocessableEntity()?.invalidParameters ?? []); + + const [pet, setPet] = createStore({ name: '', vaccinations: [] }); + + const onSubmit = () => { + props.submitPet({ ...pet }); + }; + + createEffect(() => { + const defaultPet = props.getDefaultPet ? props.getDefaultPet() : undefined; + if (defaultPet) { + setPet(defaultPet); + } + }); + + return ( +
{ + e.preventDefault(); + e.stopPropagation(); + onSubmit(); + }} + > +
+ pet.name} + setValue={(value) => setPet('name', value)} + getInvalidParametersOrUndefined={() => getInvalidParameterByNameDenormalized().get(`name`)} + /> + pet.tag ?? ''} + setValue={(value) => setPet('tag', value === '' ? undefined : value)} + getInvalidParametersOrUndefined={() => getInvalidParameterByNameDenormalized().get(`tag`)} + /> +
+ +
+ + {(vaccination, getIndex) => ( +
+ vaccination.name} + setValue={(value) => + setPet('vaccinations', [ + ...pet.vaccinations.map((currentVaccination, i) => { + if (i === getIndex()) { + return { ...currentVaccination, name: value }; + } + + return currentVaccination; + }), + ]) + } + getInvalidParametersOrUndefined={() => + getInvalidParameterByNameDenormalized().get(`vaccinations[${getIndex()}][name]`) ?? + getInvalidParameterByNameDenormalized().get(`vaccinations[${getIndex()}].name`) + } + /> + +
+ )} +
+ +
+
+ +
+
+ ); +}; diff --git a/src/component/heading.tsx b/src/component/heading.tsx new file mode 100644 index 0000000..0c86f9c --- /dev/null +++ b/src/component/heading.tsx @@ -0,0 +1,9 @@ +import { Component, JSX } from 'solid-js'; + +type H1Props = { + children: JSX.Element | string; +}; + +export const H1: Component = (props: H1Props) => { + return

{props.children}

; +}; diff --git a/src/component/page/home.tsx b/src/component/page/home.tsx new file mode 100644 index 0000000..1c68993 --- /dev/null +++ b/src/component/page/home.tsx @@ -0,0 +1,20 @@ +import { Component, createEffect, onCleanup } from 'solid-js'; +import { H1 } from '../heading'; + +const Home: Component = () => { + createEffect(() => { + document.title = 'Home'; + }); + + onCleanup(() => { + document.title = ''; + }); + + return ( +
+

Home

+
+ ); +}; + +export default Home; diff --git a/src/component/page/not-found.tsx b/src/component/page/not-found.tsx new file mode 100644 index 0000000..74c9a72 --- /dev/null +++ b/src/component/page/not-found.tsx @@ -0,0 +1,20 @@ +import { Component, createEffect, onCleanup } from 'solid-js'; +import { H1 } from '../heading'; + +const NotFound: Component = () => { + createEffect(() => { + document.title = 'Not Found'; + }); + + onCleanup(() => { + document.title = ''; + }); + + return ( +
+

Not Found

+
+ ); +}; + +export default NotFound; diff --git a/src/component/page/pet/create.tsx b/src/component/page/pet/create.tsx new file mode 100644 index 0000000..a0ef625 --- /dev/null +++ b/src/component/page/pet/create.tsx @@ -0,0 +1,54 @@ +import { Component, Show, createEffect, createSignal, onCleanup } from 'solid-js'; +import { H1 } from '../../heading'; +import { HttpError, BadRequestOrUnprocessableEntity } from '../../../api-client/error'; +import { useNavigate } from '@solidjs/router'; +import { CreatePet } from '../../../api-client/pet'; +import { HttpError as HttpErrorPartial } from '../../partial/http-error'; +import { PetForm } from '../../form/pet-form'; +import { AnchorButton } from '../../button'; +import { PetRequest } from '../../../model/model'; + +const PetCreate: Component = () => { + const navigate = useNavigate(); + + const [getHttpErrorOrUndefined, setHttpErrorOrUndefined] = createSignal(); + + const getBadRequestOrUnprocessableEntity = () => { + const httpErrorOrUndefined = getHttpErrorOrUndefined(); + + return httpErrorOrUndefined instanceof BadRequestOrUnprocessableEntity ? httpErrorOrUndefined : undefined; + }; + + const submitPet = async (pet: PetRequest) => { + const response = await CreatePet(pet); + + if (response instanceof HttpError) { + setHttpErrorOrUndefined(response); + } else { + setHttpErrorOrUndefined(undefined); + + navigate('/pet'); + } + }; + + createEffect(() => { + document.title = 'Pet Create'; + }); + + onCleanup(() => { + document.title = ''; + }); + + return ( +
+ {(getHttpError) => } +

Create Pet

+ + + List + +
+ ); +}; + +export default PetCreate; diff --git a/src/component/page/pet/list.tsx b/src/component/page/pet/list.tsx new file mode 100644 index 0000000..7b8b11c --- /dev/null +++ b/src/component/page/pet/list.tsx @@ -0,0 +1,217 @@ +import { Component, createEffect, onCleanup, createSignal, Show, For } from 'solid-js'; +import { A, useNavigate, useLocation } from '@solidjs/router'; +import qs from 'qs'; +import { PetFilters, PetList } from '../../../model/model'; +import { DeletePet, ListPets } from '../../../api-client/pet'; +import { HttpError as HttpErrorPartial } from '../../partial/http-error'; +import { BadRequest, HttpError } from '../../../api-client/error'; +import { H1 } from '../../heading'; +import { format } from 'date-fns'; +import { Pagination } from '../../partial/pagination'; +import { de } from 'date-fns/locale'; +import { Table, Tbody, Td, Th, Thead, Tr } from '../../table'; +import { AnchorButton, Button } from '../../button'; +import { PetFiltersForm } from '../../form/pet-filters-form'; + +const PetListComponent: Component = () => { + const navigate = useNavigate(); + const location = useLocation(); + + const [getPetListOrUndefined, setPetListOrUndefined] = createSignal(); + const [getHttpErrorOrUndefined, setHttpErrorOrUndefined] = createSignal(); + + const getParsedQuery = () => qs.parse(location.search.substring(1)); + + const getQuery = () => { + const parsedQuery = getParsedQuery(); + + return { + page: typeof parsedQuery.page === 'string' ? parseInt(parsedQuery.page) : 1, + filters: + typeof parsedQuery.filters === 'object' && !(parsedQuery.filters instanceof Array) ? parsedQuery.filters : {}, + sort: typeof parsedQuery.sort === 'object' && !(parsedQuery.sort instanceof Array) ? parsedQuery.sort : {}, + }; + }; + + const getQueryString = () => { + const query = getQuery(); + + return qs.stringify({ + limit: 10, + offset: query.page * 10 - 10, + filters: query.filters, + sort: query.sort, + }); + }; + + const fetchPetList = async () => { + const response = await ListPets(getQueryString()); + + if (response instanceof HttpError) { + setHttpErrorOrUndefined(response); + } else { + setHttpErrorOrUndefined(undefined); + setPetListOrUndefined(response); + } + }; + + const deletePet = async (id: string) => { + const deleteResponse = await DeletePet(id); + + if (deleteResponse instanceof HttpError) { + setHttpErrorOrUndefined(deleteResponse); + } else { + setHttpErrorOrUndefined(undefined); + fetchPetList(); + } + }; + + const submitPage = (page: number): void => { + const query = getQuery(); + + navigate(`/pet?${qs.stringify({ ...query, page })}`); + }; + + const submitPetFilters = (filters: PetFilters): void => { + const query = getQuery(); + + navigate(`/pet?${qs.stringify({ ...query, page: 1, filters })}`); + }; + + const sortLink = (field: string, order?: string): string => { + const query = getQuery(); + + return `/pet?${qs.stringify({ + query, + sort: { ...query.sort, [field]: order }, + })}`; + }; + + const getCurrentPage = () => getQuery().page; + const getTotalPages = () => { + const petListOrUndefined = getPetListOrUndefined(); + + return petListOrUndefined && petListOrUndefined.count > 0 + ? Math.ceil(petListOrUndefined.count / petListOrUndefined.limit) + : 1; + }; + const getMaxPages = () => 7; + + createEffect(() => { + document.title = 'Pet List'; + + fetchPetList(); + }); + + onCleanup(() => { + document.title = ''; + }); + + return ( + +
+ + {(getHttpError) => } + +

Pet List

+ + {(getPetList) => ( +
+ + + Create + + +
+ { + const httpErrorOrUndefined = getHttpErrorOrUndefined(); + + return httpErrorOrUndefined instanceof BadRequest ? httpErrorOrUndefined : undefined; + }} + getDefaultPetFilters={() => getQuery().filters} + submitPetFilters={submitPetFilters} + /> +
+ + + + + + + + + + + + + + {(pet, i) => ( + + + + + + + + + )} + + +
IdCreatedAtUpdatedAt + Name ( + + A-Z + + | + + Z-A + + | + + --- + + ) + TagActions
{pet.id}{format(Date.parse(pet.createdAt), 'dd.MM.yyyy - HH:mm:ss', { locale: de })} + {pet.updatedAt && format(Date.parse(pet.updatedAt), 'dd.MM.yyyy - HH:mm:ss', { locale: de })} + {pet.name}{pet.tag} + + + Read + + + + + Update + + + + + +
+ +
+ )} +
+
+
+ ); +}; + +export default PetListComponent; diff --git a/src/component/page/pet/read.tsx b/src/component/page/pet/read.tsx new file mode 100644 index 0000000..3f2e30f --- /dev/null +++ b/src/component/page/pet/read.tsx @@ -0,0 +1,87 @@ +import { Component, For, Show, createEffect, createSignal, onCleanup } from 'solid-js'; +import { H1 } from '../../heading'; +import { useParams } from '@solidjs/router'; +import { PetResponse } from '../../../model/model'; +import { HttpError } from '../../../api-client/error'; +import { ReadPet } from '../../../api-client/pet'; +import { HttpError as HttpErrorPartial } from '../../partial/http-error'; +import { AnchorButton } from '../../button'; +import { de } from 'date-fns/locale'; +import { format } from 'date-fns'; + +const PetRead: Component = () => { + const params = useParams(); + const id = params.id as string; + + const [getPetOrUndefined, setPetOrUndefined] = createSignal(); + const [getHttpErrorOrUndefined, setHttpErrorOrUndefined] = createSignal(); + + const fetchPet = async () => { + const response = await ReadPet(id); + + if (response instanceof HttpError) { + setHttpErrorOrUndefined(response); + } else { + setHttpErrorOrUndefined(undefined); + setPetOrUndefined(response); + } + }; + + createEffect(() => { + document.title = 'Pet Read'; + + fetchPet(); + }); + + onCleanup(() => { + document.title = ''; + }); + + return ( + +
+ + {(getHttpError) => } + +

Read Pet

+ + {(getPet) => ( +
+
+
Id
+
{getPet().id}
+
CreatedAt
+
{format(Date.parse(getPet().createdAt), 'dd.MM.yyyy - HH:mm:ss', { locale: de })}
+
UpdatedAt
+
+ + {(getUpdatedAt) => format(Date.parse(getUpdatedAt()), 'dd.MM.yyyy - HH:mm:ss', { locale: de })} + +
+
Name
+
{getPet().name}
+
Tag
+
{getPet().tag}
+
Vaccinations
+
+ + {(getVaccinations) => ( +
    + {(vaccination) =>
  • {vaccination.name}
  • }
    +
+ )} +
+
+
+
+ )} +
+ + List + +
+
+ ); +}; + +export default PetRead; diff --git a/src/component/page/pet/update.tsx b/src/component/page/pet/update.tsx new file mode 100644 index 0000000..9d624a6 --- /dev/null +++ b/src/component/page/pet/update.tsx @@ -0,0 +1,84 @@ +import { Component, Show, createEffect, createSignal, onCleanup } from 'solid-js'; +import { H1 } from '../../heading'; +import { useNavigate, useParams } from '@solidjs/router'; +import { PetRequest, PetResponse } from '../../../model/model'; +import { HttpError, BadRequestOrUnprocessableEntity } from '../../../api-client/error'; +import { ReadPet, UpdatePet } from '../../../api-client/pet'; +import { HttpError as HttpErrorPartial } from '../../partial/http-error'; +import { AnchorButton } from '../../button'; +import { PetForm } from '../../form/pet-form'; + +const PetUpdate: Component = () => { + const params = useParams(); + const id = params.id as string; + + const navigate = useNavigate(); + + const [getPetOrUndefined, setPetOrUndefined] = createSignal(); + const [getHttpErrorOrUndefined, setHttpErrorOrUndefined] = createSignal(); + + const getBadRequestOrUnprocessableEntity = () => { + const httpErrorOrUndefined = getHttpErrorOrUndefined(); + + return httpErrorOrUndefined instanceof BadRequestOrUnprocessableEntity ? httpErrorOrUndefined : undefined; + }; + + const fetchPet = async () => { + const response = await ReadPet(id); + + if (response instanceof HttpError) { + setHttpErrorOrUndefined(response); + } else { + setHttpErrorOrUndefined(undefined); + setPetOrUndefined(response); + } + }; + + const submitPet = async (petRequest: PetRequest) => { + const response = await UpdatePet(id, petRequest); + + if (response instanceof HttpError) { + setHttpErrorOrUndefined(response); + } else { + setHttpErrorOrUndefined(undefined); + setPetOrUndefined(response); + + navigate('/pet'); + } + }; + + createEffect(() => { + document.title = 'Pet Update'; + + fetchPet(); + }); + + onCleanup(() => { + document.title = ''; + }); + + return ( + +
+ + {(getHttpError) => } + +

Pet Update

+ + {(getPet) => ( + + )} + + + List + +
+
+ ); +}; + +export default PetUpdate; diff --git a/src/component/partial/http-error.tsx b/src/component/partial/http-error.tsx new file mode 100644 index 0000000..dd58481 --- /dev/null +++ b/src/component/partial/http-error.tsx @@ -0,0 +1,27 @@ +import { Component, For } from 'solid-js'; +import { HttpError as HttpErrorType, BadRequestOrUnprocessableEntity, InvalidParameter } from '../../api-client/error'; + +type HttpErrorProps = { + httpError: HttpErrorType; +}; + +export const HttpError: Component = (props: HttpErrorProps) => { + return ( +
+

{props.httpError.title}

+ {props.httpError.detail ?

{props.httpError.detail}

: null} + {props.httpError.instance ?

{props.httpError.instance}

: null} + {props.httpError instanceof BadRequestOrUnprocessableEntity && props.httpError.invalidParameters?.length ? ( +
    + + {(invalidParameter: InvalidParameter) => ( +
  • + {invalidParameter.name}: {invalidParameter.reason} +
  • + )} +
    +
+ ) : null} +
+ ); +}; diff --git a/src/component/partial/pagination.tsx b/src/component/partial/pagination.tsx new file mode 100644 index 0000000..46af2b0 --- /dev/null +++ b/src/component/partial/pagination.tsx @@ -0,0 +1,115 @@ +import { Accessor, Component, For, Show } from 'solid-js'; + +export type PaginationProps = { + submitPage: { (page: number): void }; + getCurrentPage: Accessor; + getTotalPages: Accessor; + getMaxPages: Accessor; +}; + +export const Pagination: Component = (props: PaginationProps) => { + const getPages = () => { + const currentPage = props.getCurrentPage(); + const totalPages = props.getTotalPages(); + const maxPages = props.getMaxPages(); + + if (totalPages <= 1 || maxPages <= 1 || currentPage > totalPages) { + return []; + } + + const pages = [currentPage]; + + for (let i = 1; ; i++) { + if (currentPage - i >= 1) { + pages.push(currentPage - i); + + if (pages.length === maxPages || pages.length === totalPages) { + break; + } + } + + if (currentPage + i <= totalPages) { + pages.push(currentPage + i); + + if (pages.length === maxPages || pages.length === totalPages) { + break; + } + } + } + + pages.sort((a, b) => a - b); + + return pages; + }; + + return ( + 0}> +
    + 2}> +
  • + +
  • +
    + 1}> +
  • + +
  • +
    + + {(page) => ( +
  • + +
  • + )} +
    + +
  • + +
  • +
    + +
  • + +
  • +
    +
+
+ ); +}; diff --git a/src/component/table.tsx b/src/component/table.tsx new file mode 100644 index 0000000..0283c1b --- /dev/null +++ b/src/component/table.tsx @@ -0,0 +1,80 @@ +import { Component, JSX } from 'solid-js'; + +type TableProps = { + class?: string; + children: JSX.Element | string; +}; + +export const Table: Component = (props: TableProps) => { + return
{props.children}
; +}; + +type TheadProps = { + class?: string; + children: JSX.Element | string; +}; + +export const Thead: Component = (props: TheadProps) => { + return
{props.children}
; +}; + +type TbodyProps = { + class?: string; + children: JSX.Element | string; +}; + +export const Tbody: Component = (props: TbodyProps) => { + return
{props.children}
; +}; + +type TfootProps = { + class?: string; + children: JSX.Element | string; +}; + +export const Tfoot: Component = (props: TfootProps) => { + return
{props.children}
; +}; + +type TrProps = { + class?: string; + children: JSX.Element | string; +}; + +export const Tr: Component = (props: TrProps) => { + return
{props.children}
; +}; + +type ThProps = { + class?: string; + children: JSX.Element | string; +}; + +export const Th: Component = (props: ThProps) => { + return ( +
+ {props.children} +
+ ); +}; + +type TdProps = { + class?: string; + children: JSX.Element | string; +}; + +export const Td: Component = (props: TdProps) => { + return ( +
+ {props.children} +
+ ); +}; diff --git a/src/denormalizer/invalid-parameter-by-name-denormalizer.ts b/src/denormalizer/invalid-parameter-by-name-denormalizer.ts new file mode 100644 index 0000000..29c7619 --- /dev/null +++ b/src/denormalizer/invalid-parameter-by-name-denormalizer.ts @@ -0,0 +1,18 @@ +import { InvalidParameter } from '../api-client/error'; + +const InvalidParameterByNameDenormalizer = ( + invalidParameters: Array, +): Map> => { + const errorsByFields = new Map>(); + invalidParameters.forEach((invalidParameter: InvalidParameter) => { + if (!errorsByFields.has(invalidParameter.name)) { + errorsByFields.set(invalidParameter.name, []); + } + + errorsByFields.get(invalidParameter.name)?.push(invalidParameter); + }); + + return errorsByFields; +}; + +export default InvalidParameterByNameDenormalizer; diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..dbfb140 --- /dev/null +++ b/src/index.css @@ -0,0 +1,10 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +html, +body, +#root { + @apply w-full; + @apply h-full; +} diff --git a/src/index.tsx b/src/index.tsx new file mode 100644 index 0000000..645b5ab --- /dev/null +++ b/src/index.tsx @@ -0,0 +1,15 @@ +/* @refresh reload */ +import { render } from 'solid-js/web'; +import './index.css'; +import Routes from './routes'; +import { Router } from '@solidjs/router'; +import App from './app'; + +render( + () => ( + + + + ), + document.getElementById('root')!, +); diff --git a/src/model/model.ts b/src/model/model.ts new file mode 100644 index 0000000..05bc626 --- /dev/null +++ b/src/model/model.ts @@ -0,0 +1,53 @@ +import { z } from 'zod'; + +const linkSchema = z.object({ + href: z.string(), +}); + +export const petRequestSchema = z.object({ + name: z.string(), + tag: z.string().nullish(), + vaccinations: z.array( + z.object({ + name: z.string(), + }), + ), +}); + +export type PetRequest = z.infer; + +export const petResponseSchema = z.object({ + id: z.string(), + createdAt: z.string(), + updatedAt: z.string().nullish(), + ...petRequestSchema.shape, + _links: z + .object({ + read: linkSchema.optional(), + update: linkSchema.optional(), + delete: linkSchema.optional(), + }) + .optional(), +}); + +export type PetResponse = z.infer; + +export const petFiltersSchema = z.object({ + name: z.string().optional(), +}); + +export type PetFilters = z.infer; + +export const petListSchema = z.object({ + offset: z.number(), + limit: z.number(), + count: z.number(), + items: z.array(petResponseSchema), + _links: z + .object({ + create: linkSchema.optional(), + }) + .optional(), +}); + +export type PetList = z.infer; diff --git a/src/routes.tsx b/src/routes.tsx new file mode 100644 index 0000000..7bbb277 --- /dev/null +++ b/src/routes.tsx @@ -0,0 +1,24 @@ +import { Route } from '@solidjs/router'; +import { Component, lazy } from 'solid-js'; + +const Home = lazy(() => import('./component/page/home')); +const NotFound = lazy(() => import('./component/page/not-found')); +const PetCreate = lazy(() => import('./component/page/pet/create')); +const PetList = lazy(() => import('./component/page/pet/list')); +const PetRead = lazy(() => import('./component/page/pet/read')); +const PetUpdate = lazy(() => import('./component/page/pet/update')); + +const Routes: Component = () => { + return ( + <> + + + + + + + + ); +}; + +export default Routes; diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..a6d25e1 --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,10 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: [ + './src/**/*.{jsx,tsx}', + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/tests/api-client/pet.test.ts b/tests/api-client/pet.test.ts new file mode 100644 index 0000000..4913093 --- /dev/null +++ b/tests/api-client/pet.test.ts @@ -0,0 +1,826 @@ +import { ListPets, CreatePet, ReadPet, UpdatePet, DeletePet } from '../../src/api-client/pet'; +import fetchMock from 'fetch-mock'; +import { describe, test, expect, beforeEach } from 'vitest'; +import { PetList, PetRequest, PetResponse } from '../../src/model/model'; +import { + BadRequest, + InternalServerError, + NetworkError, + NotFound, + UnprocessableEntity, +} from '../../src/api-client/error'; + +beforeEach(() => { + fetchMock.restore(); +}); + +describe('list pets', () => { + test('success', async () => { + fetchMock.get( + 'https://petstore.test/api/pets?sort[name]=asc', + { + status: 200, + headers: { + 'Content-Type': 'application/json', + }, + body: { offset: 0, limit: 20, count: 35, items: [], _links: { create: { href: '' } } }, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + }, + }, + ); + + const response = (await ListPets('sort[name]=asc')) as PetList; + + expect(response).toHaveProperty('offset'); + expect(response.offset).toEqual(0); + + expect(response).toHaveProperty('limit'); + expect(response.limit).toEqual(20); + + expect(response).toHaveProperty('count'); + expect(response.count).toEqual(35); + }); + + test('bad request', async () => { + fetchMock.get( + 'https://petstore.test/api/pets?sort[name]=asc', + { + status: 400, + headers: { + 'Content-Type': 'application/json', + }, + body: { + title: 'Bad Request', + detail: 'Sorting value', + instance: '0123456789abcdef', + invalidParameters: [{ name: 'name', reason: 'unknown field', details: { key: 'value1' } }], + }, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + }, + }, + ); + + const response = (await ListPets('sort[name]=asc')) as BadRequest; + + expect(response).toBeInstanceOf(BadRequest); + + expect(response.title).toEqual('Bad Request'); + expect(response.detail).toEqual('Sorting value'); + expect(response.instance).toEqual('0123456789abcdef'); + }); + + test('internal server error', async () => { + fetchMock.get( + 'https://petstore.test/api/pets?sort[name]=asc', + { + status: 500, + headers: { + 'Content-Type': 'application/json', + }, + body: { + title: 'Internal Server Error', + instance: '0123456789abcdef', + }, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + }, + }, + ); + + const response = (await ListPets('sort[name]=asc')) as InternalServerError; + + expect(response).toBeInstanceOf(InternalServerError); + + expect(response.title).toEqual('Internal Server Error'); + expect(response.instance).toEqual('0123456789abcdef'); + }); + + test('network error', async () => { + fetchMock.get( + 'https://petstore.test/api/pets?sort[name]=asc', + { + throws: new TypeError('Failed to fetch'), + }, + { + delay: 10, + headers: { + Accept: 'application/json', + }, + }, + ); + + const response = (await ListPets('sort[name]=asc')) as NetworkError; + + expect(response).toBeInstanceOf(NetworkError); + + expect(response.title).toEqual('Failed to fetch'); + }); + + test('unknown response', async () => { + fetchMock.get( + 'https://petstore.test/api/pets?sort[name]=asc', + { + status: 418, + headers: { + 'Content-Type': 'application/json', + }, + body: {}, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + }, + }, + ); + + expect.assertions(1); + + await expect(ListPets('sort[name]=asc')).rejects.toThrow(new Error('Unknown response')); + }); +}); + +describe('create pet', () => { + test('success', async () => { + const pet: PetRequest = { name: 'Brownie', vaccinations: [] }; + + fetchMock.post( + 'https://petstore.test/api/pets', + { + status: 201, + headers: { + 'Content-Type': 'application/json', + }, + body: { id: '4d783b77-eb09-4603-b99b-f590b605eaa9', createdAt: '2022-06-12T20:08:24.793Z', ...pet }, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.parse(JSON.stringify(pet)), + }, + ); + + const response = (await CreatePet(pet)) as PetResponse; + + expect(response).toHaveProperty('id'); + expect(response.id).toEqual('4d783b77-eb09-4603-b99b-f590b605eaa9'); + expect(response).toHaveProperty('name'); + expect(response.name).toEqual('Brownie'); + }); + + test('bad request', async () => { + const pet: PetRequest = { name: '', vaccinations: [] }; + + fetchMock.post( + 'https://petstore.test/api/pets', + { + status: 400, + headers: { + 'Content-Type': 'application/json', + }, + body: { + title: 'Bad Request', + detail: 'name', + instance: '0123456789abcdef', + invalidParameters: [{ name: 'name', reason: 'empty', details: { key: 'value1' } }], + }, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.parse(JSON.stringify(pet)), + }, + ); + + const response = (await CreatePet(pet)) as BadRequest; + + expect(response).toBeInstanceOf(BadRequest); + + expect(response.title).toEqual('Bad Request'); + expect(response.detail).toEqual('name'); + expect(response.instance).toEqual('0123456789abcdef'); + }); + + test('unprocessable entity', async () => { + const pet: PetRequest = { name: '', vaccinations: [] }; + + fetchMock.post( + 'https://petstore.test/api/pets', + { + status: 422, + headers: { + 'Content-Type': 'application/json', + }, + body: { + title: 'Unprocessable Entity', + detail: 'name', + instance: '0123456789abcdef', + invalidParameters: [{ name: 'name', reason: 'empty', details: { key: 'value1' } }], + }, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.parse(JSON.stringify(pet)), + }, + ); + + const response = (await CreatePet(pet)) as UnprocessableEntity; + + expect(response).toBeInstanceOf(UnprocessableEntity); + + expect(response.title).toEqual('Unprocessable Entity'); + expect(response.detail).toEqual('name'); + expect(response.instance).toEqual('0123456789abcdef'); + }); + + test('internal server error', async () => { + const pet: PetRequest = { name: 'Brownie', vaccinations: [] }; + + fetchMock.post( + 'https://petstore.test/api/pets', + { + status: 500, + headers: { + 'Content-Type': 'application/json', + }, + body: { + title: 'Internal Server Error', + instance: '0123456789abcdef', + }, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.parse(JSON.stringify(pet)), + }, + ); + + const response = (await CreatePet(pet)) as InternalServerError; + + expect(response).toBeInstanceOf(InternalServerError); + + expect(response.title).toEqual('Internal Server Error'); + expect(response.instance).toEqual('0123456789abcdef'); + }); + + test('network error', async () => { + const pet: PetRequest = { name: 'Brownie', vaccinations: [] }; + + fetchMock.post( + 'https://petstore.test/api/pets', + { + throws: new TypeError('Failed to fetch'), + }, + { + delay: 10, + headers: { + Accept: 'application/json', + }, + body: JSON.parse(JSON.stringify(pet)), + }, + ); + + const response = (await CreatePet(pet)) as NetworkError; + + expect(response).toBeInstanceOf(NetworkError); + + expect(response.title).toEqual('Failed to fetch'); + }); + + test('unknown response', async () => { + const pet: PetRequest = { name: 'Brownie', vaccinations: [] }; + + fetchMock.post( + 'https://petstore.test/api/pets', + { + status: 418, + headers: { + 'Content-Type': 'application/json', + }, + body: {}, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + }, + body: JSON.parse(JSON.stringify(pet)), + }, + ); + + expect.assertions(1); + + await expect(CreatePet(pet)).rejects.toThrow(new Error('Unknown response')); + }); +}); + +describe('read pet', () => { + test('success', async () => { + fetchMock.get( + 'https://petstore.test/api/pets/4d783b77-eb09-4603-b99b-f590b605eaa9', + { + status: 200, + headers: { + 'Content-Type': 'application/json', + }, + body: { + id: '4d783b77-eb09-4603-b99b-f590b605eaa9', + createdAt: '2022-06-12T20:08:24.793Z', + name: 'Brownie', + vaccinations: [], + }, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + }, + }, + ); + + const response = (await ReadPet('4d783b77-eb09-4603-b99b-f590b605eaa9')) as PetResponse; + + expect(response).toHaveProperty('id'); + expect(response.id).toEqual('4d783b77-eb09-4603-b99b-f590b605eaa9'); + expect(response).toHaveProperty('name'); + expect(response.name).toEqual('Brownie'); + }); + + test('not found', async () => { + fetchMock.get( + 'https://petstore.test/api/pets/4d783b77-eb09-4603-b99b-f590b605eaa9', + { + status: 404, + headers: { + 'Content-Type': 'application/json', + }, + body: { + title: 'Not Found', + detail: 'There is no pet with id "4d783b77-eb09-4603-b99b-f590b605eaa9"', + instance: '0123456789abcdef', + }, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + }, + }, + ); + + const response = (await ReadPet('4d783b77-eb09-4603-b99b-f590b605eaa9')) as NotFound; + + expect(response).toBeInstanceOf(NotFound); + + expect(response.title).toEqual('Not Found'); + expect(response.detail).toEqual('There is no pet with id "4d783b77-eb09-4603-b99b-f590b605eaa9"'); + expect(response.instance).toEqual('0123456789abcdef'); + }); + + test('internal server error', async () => { + fetchMock.get( + 'https://petstore.test/api/pets/4d783b77-eb09-4603-b99b-f590b605eaa9', + { + status: 500, + headers: { + 'Content-Type': 'application/json', + }, + body: { + title: 'Internal Server Error', + instance: '0123456789abcdef', + }, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + }, + }, + ); + + const response = (await ReadPet('4d783b77-eb09-4603-b99b-f590b605eaa9')) as InternalServerError; + + expect(response).toBeInstanceOf(InternalServerError); + + expect(response.title).toEqual('Internal Server Error'); + expect(response.instance).toEqual('0123456789abcdef'); + }); + + test('network error', async () => { + fetchMock.get( + 'https://petstore.test/api/pets/4d783b77-eb09-4603-b99b-f590b605eaa9', + { + throws: new TypeError('Failed to fetch'), + }, + { + delay: 10, + headers: { + Accept: 'application/json', + }, + }, + ); + + const response = (await ReadPet('4d783b77-eb09-4603-b99b-f590b605eaa9')) as NetworkError; + + expect(response).toBeInstanceOf(NetworkError); + + expect(response.title).toEqual('Failed to fetch'); + }); + + test('unknown response', async () => { + fetchMock.get( + 'https://petstore.test/api/pets/4d783b77-eb09-4603-b99b-f590b605eaa9', + { + status: 418, + headers: { + 'Content-Type': 'application/json', + }, + body: {}, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + }, + }, + ); + + expect.assertions(1); + + await expect(ReadPet('4d783b77-eb09-4603-b99b-f590b605eaa9')).rejects.toThrow(new Error('Unknown response')); + }); +}); + +describe('update pet', () => { + test('success', async () => { + const pet: PetRequest = { name: 'Brownie', vaccinations: [] }; + + fetchMock.put( + 'https://petstore.test/api/pets/4d783b77-eb09-4603-b99b-f590b605eaa9', + { + status: 200, + headers: { + 'Content-Type': 'application/json', + }, + body: { + id: '4d783b77-eb09-4603-b99b-f590b605eaa9', + createdAt: '2022-06-12T20:08:24.793Z', + updatedAt: '2022-06-12T20:08:24.793Z', + ...pet, + }, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.parse(JSON.stringify(pet)), + }, + ); + + const response = (await UpdatePet('4d783b77-eb09-4603-b99b-f590b605eaa9', pet)) as PetResponse; + + expect(response).toHaveProperty('id'); + expect(response.id).toEqual('4d783b77-eb09-4603-b99b-f590b605eaa9'); + expect(response).toHaveProperty('name'); + expect(response.name).toEqual('Brownie'); + }); + + test('bad request', async () => { + const pet: PetRequest = { name: '', vaccinations: [] }; + + fetchMock.put( + 'https://petstore.test/api/pets/4d783b77-eb09-4603-b99b-f590b605eaa9', + { + status: 400, + headers: { + 'Content-Type': 'application/json', + }, + body: { + title: 'Bad Request', + detail: 'name', + instance: '0123456789abcdef', + invalidParameters: [{ name: 'name', reason: 'empty', details: { key: 'value1' } }], + }, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.parse(JSON.stringify(pet)), + }, + ); + + const response = (await UpdatePet('4d783b77-eb09-4603-b99b-f590b605eaa9', pet)) as BadRequest; + + expect(response).toBeInstanceOf(BadRequest); + + expect(response.title).toEqual('Bad Request'); + expect(response.detail).toEqual('name'); + expect(response.instance).toEqual('0123456789abcdef'); + }); + + test('not found', async () => { + const pet: PetRequest = { name: 'Brownie', vaccinations: [] }; + + fetchMock.put( + 'https://petstore.test/api/pets/4d783b77-eb09-4603-b99b-f590b605eaa9', + { + status: 404, + headers: { + 'Content-Type': 'application/json', + }, + body: { + title: 'Not Found', + detail: 'There is no pet with id "4d783b77-eb09-4603-b99b-f590b605eaa9"', + instance: '0123456789abcdef', + }, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.parse(JSON.stringify(pet)), + }, + ); + + const response = (await UpdatePet('4d783b77-eb09-4603-b99b-f590b605eaa9', pet)) as NotFound; + + expect(response).toBeInstanceOf(NotFound); + + expect(response.title).toEqual('Not Found'); + expect(response.detail).toEqual('There is no pet with id "4d783b77-eb09-4603-b99b-f590b605eaa9"'); + expect(response.instance).toEqual('0123456789abcdef'); + }); + + test('unprocessable entity', async () => { + const pet: PetRequest = { name: '', vaccinations: [] }; + + fetchMock.put( + 'https://petstore.test/api/pets/4d783b77-eb09-4603-b99b-f590b605eaa9', + { + status: 422, + headers: { + 'Content-Type': 'application/json', + }, + body: { + title: 'Unprocessable Entity', + detail: 'name', + instance: '0123456789abcdef', + invalidParameters: [{ name: 'name', reason: 'empty', details: { key: 'value1' } }], + }, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.parse(JSON.stringify(pet)), + }, + ); + + const response = (await UpdatePet('4d783b77-eb09-4603-b99b-f590b605eaa9', pet)) as UnprocessableEntity; + + expect(response).toBeInstanceOf(UnprocessableEntity); + + expect(response.title).toEqual('Unprocessable Entity'); + expect(response.detail).toEqual('name'); + expect(response.instance).toEqual('0123456789abcdef'); + }); + + test('internal server error', async () => { + const pet: PetRequest = { name: 'Brownie', vaccinations: [] }; + + fetchMock.put( + 'https://petstore.test/api/pets/4d783b77-eb09-4603-b99b-f590b605eaa9', + { + status: 500, + headers: { + 'Content-Type': 'application/json', + }, + body: { + title: 'Internal Server Error', + instance: '0123456789abcdef', + }, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.parse(JSON.stringify(pet)), + }, + ); + + const response = (await UpdatePet('4d783b77-eb09-4603-b99b-f590b605eaa9', pet)) as InternalServerError; + + expect(response).toBeInstanceOf(InternalServerError); + + expect(response.title).toEqual('Internal Server Error'); + expect(response.instance).toEqual('0123456789abcdef'); + }); + + test('network error', async () => { + const pet: PetRequest = { name: 'Brownie', vaccinations: [] }; + + fetchMock.put( + 'https://petstore.test/api/pets/4d783b77-eb09-4603-b99b-f590b605eaa9', + { + throws: new TypeError('Failed to fetch'), + }, + { + delay: 10, + headers: { + Accept: 'application/json', + }, + body: JSON.parse(JSON.stringify(pet)), + }, + ); + + const response = (await UpdatePet('4d783b77-eb09-4603-b99b-f590b605eaa9', pet)) as NetworkError; + + expect(response).toBeInstanceOf(NetworkError); + + expect(response.title).toEqual('Failed to fetch'); + }); + + test('unknown response', async () => { + const pet: PetRequest = { name: 'Brownie', vaccinations: [] }; + + fetchMock.put( + 'https://petstore.test/api/pets/4d783b77-eb09-4603-b99b-f590b605eaa9', + { + status: 418, + headers: { + 'Content-Type': 'application/json', + }, + body: {}, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + }, + body: JSON.parse(JSON.stringify(pet)), + }, + ); + + expect.assertions(1); + + await expect(UpdatePet('4d783b77-eb09-4603-b99b-f590b605eaa9', pet)).rejects.toThrow(new Error('Unknown response')); + }); +}); + +describe('delete pet', () => { + test('success', async () => { + fetchMock.delete( + 'https://petstore.test/api/pets/4d783b77-eb09-4603-b99b-f590b605eaa9', + { + status: 204, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + }, + }, + ); + + await DeletePet('4d783b77-eb09-4603-b99b-f590b605eaa9'); + }); + + test('not found', async () => { + fetchMock.delete( + 'https://petstore.test/api/pets/4d783b77-eb09-4603-b99b-f590b605eaa9', + { + status: 404, + headers: { + 'Content-Type': 'application/json', + }, + body: { + title: 'Not Found', + detail: 'There is no pet with id "4d783b77-eb09-4603-b99b-f590b605eaa9"', + instance: '0123456789abcdef', + }, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + }, + }, + ); + + const response = (await DeletePet('4d783b77-eb09-4603-b99b-f590b605eaa9')) as NotFound; + + expect(response).toBeInstanceOf(NotFound); + + expect(response.title).toEqual('Not Found'); + expect(response.detail).toEqual('There is no pet with id "4d783b77-eb09-4603-b99b-f590b605eaa9"'); + expect(response.instance).toEqual('0123456789abcdef'); + }); + + test('internal server error', async () => { + fetchMock.delete( + 'https://petstore.test/api/pets/4d783b77-eb09-4603-b99b-f590b605eaa9', + { + status: 500, + headers: { + 'Content-Type': 'application/json', + }, + body: { + title: 'Internal Server Error', + instance: '0123456789abcdef', + }, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + }, + }, + ); + + const response = (await DeletePet('4d783b77-eb09-4603-b99b-f590b605eaa9')) as InternalServerError; + + expect(response).toBeInstanceOf(InternalServerError); + + expect(response.title).toEqual('Internal Server Error'); + expect(response.instance).toEqual('0123456789abcdef'); + }); + + test('network error', async () => { + fetchMock.delete( + 'https://petstore.test/api/pets/4d783b77-eb09-4603-b99b-f590b605eaa9', + { + throws: new TypeError('Failed to fetch'), + }, + { + delay: 10, + headers: { + Accept: 'application/json', + }, + }, + ); + + const response = (await DeletePet('4d783b77-eb09-4603-b99b-f590b605eaa9')) as NetworkError; + + expect(response).toBeInstanceOf(NetworkError); + + expect(response.title).toEqual('Failed to fetch'); + }); + + test('unknown response', async () => { + fetchMock.delete( + 'https://petstore.test/api/pets/4d783b77-eb09-4603-b99b-f590b605eaa9', + { + status: 418, + headers: { + 'Content-Type': 'application/json', + }, + body: {}, + }, + { + delay: 10, + headers: { + Accept: 'application/json', + }, + }, + ); + + expect.assertions(1); + + await expect(DeletePet('4d783b77-eb09-4603-b99b-f590b605eaa9')).rejects.toThrow(new Error('Unknown response')); + }); +}); diff --git a/tests/app.test.tsx b/tests/app.test.tsx new file mode 100644 index 0000000..0758c05 --- /dev/null +++ b/tests/app.test.tsx @@ -0,0 +1,102 @@ +/** @jsxImportSource solid-js */ + +import { test, expect } from 'vitest'; +import { formatHtml } from './formatter'; +import { render, screen } from '@solidjs/testing-library'; +import App from '../src/app'; +import { Router } from '@solidjs/router'; +import userEvent from '@testing-library/user-event'; + +test('close navigation', () => { + const { container } = render(() => ); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+ + +
+
+
+ " + `); +}); + +test('open navigation', async () => { + const { container } = render(() => ); + + const navigationToggle = await screen.findByTestId('navigation-toggle'); + + await userEvent.click(navigationToggle); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+ + +
+
+
+ " + `); +}); diff --git a/tests/component/form/pet-filters-form.test.tsx b/tests/component/form/pet-filters-form.test.tsx new file mode 100644 index 0000000..7376c6a --- /dev/null +++ b/tests/component/form/pet-filters-form.test.tsx @@ -0,0 +1,182 @@ +/** @jsxImportSource solid-js */ + +import { test, expect, vi } from 'vitest'; +import { formatHtml } from '../../formatter'; +import { PetFiltersForm } from '../../../src/component/form/pet-filters-form'; +import { render, screen } from '@solidjs/testing-library'; +import { BadRequest } from '../../../src/api-client/error'; +import userEvent from '@testing-library/user-event'; +import { PetFilters } from '../../../src/model/model'; + +test('default', () => { + const getBadRequest = () => undefined; + const getDefaultPetFilters = () => ({}); + const submitPetFilters = () => {}; + + const { container } = render(() => ( + + )); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+
+
+ +
+ +
+
+
+ " + `); +}); + +test('bad request - with query string name', () => { + const getBadRequest = () => + new BadRequest({ title: 'bad request', invalidParameters: [{ name: 'filters[name]', reason: 'reason' }] }); + const getDefaultPetFilters = () => ({}); + const submitPetFilters = () => {}; + + const { container } = render(() => ( + + )); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+
+
+ +
    +
  • reason
  • +
+
+ +
+
+
+ " + `); +}); + +test('bad request - with custom string name', () => { + const getBadRequest = () => + new BadRequest({ title: 'bad request', invalidParameters: [{ name: 'filters.name', reason: 'reason' }] }); + const getDefaultPetFilters = () => ({}); + const submitPetFilters = () => {}; + + const { container } = render(() => ( + + )); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+
+
+ +
    +
  • reason
  • +
+
+ +
+
+
+ " + `); +}); + +test('submit with name', async () => { + const getBadRequest = () => undefined; + const getDefaultPetFilters = () => ({ name: 'Brown' }); + const submitPetFilters = vi.fn((petFilters: PetFilters) => { + expect(petFilters).toEqual({ name: 'Brownie' }); + }); + + render(() => ( + + )); + + const nameField = await screen.findByTestId('pet-filter-input-name'); + + await userEvent.type(nameField, 'ie'); + + const testButton = await screen.findByTestId('pet-filter-submit'); + + await userEvent.click(testButton); + + expect(submitPetFilters).toHaveBeenCalledTimes(1); +}); + +test('submit without name', async () => { + const getBadRequest = () => undefined; + const getDefaultPetFilters = () => ({ name: '' }); + const submitPetFilters = vi.fn((petFilters: PetFilters) => { + expect(petFilters).toEqual({ name: undefined }); + }); + + render(() => ( + + )); + + const nameField = await screen.findByTestId('pet-filter-input-name'); + + await userEvent.type(nameField, '{enter}'); + + expect(submitPetFilters).toHaveBeenCalledTimes(1); +}); diff --git a/tests/component/page/home.test.tsx b/tests/component/page/home.test.tsx new file mode 100644 index 0000000..1305ea3 --- /dev/null +++ b/tests/component/page/home.test.tsx @@ -0,0 +1,19 @@ +/** @jsxImportSource solid-js */ + +import { render } from '@solidjs/testing-library'; +import Home from '../../../src/component/page/home'; +import { test, expect } from 'vitest'; +import { formatHtml } from '../../formatter'; + +test('default', () => { + const { container } = render(() => ); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+

Home

+
+
+ " + `); +}); diff --git a/tests/component/page/not-found.test.tsx b/tests/component/page/not-found.test.tsx new file mode 100644 index 0000000..35f90db --- /dev/null +++ b/tests/component/page/not-found.test.tsx @@ -0,0 +1,21 @@ +/** @jsxImportSource solid-js */ + +import { render } from '@solidjs/testing-library'; +import NotFound from '../../../src/component/page/not-found'; +import { test, expect } from 'vitest'; +import { formatHtml } from '../../formatter'; + +test('default', () => { + const { container } = render(() => ); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+

+ Not Found +

+
+
+ " + `); +}); diff --git a/tests/component/page/pet/create.test.tsx b/tests/component/page/pet/create.test.tsx new file mode 100644 index 0000000..66b7de4 --- /dev/null +++ b/tests/component/page/pet/create.test.tsx @@ -0,0 +1,245 @@ +/** @jsxImportSource solid-js */ + +import Create from '../../../../src/component/page/pet/create'; +import { PetFormProps } from '../../../../src/component/form/pet-form'; +import userEvent from '@testing-library/user-event'; +import { vi } from 'vitest'; +import { test, expect } from 'vitest'; +import { PetRequest, PetResponse } from '../../../../src/model/model'; +import { formatHtml } from '../../../formatter'; +import { NetworkError, UnprocessableEntity } from '../../../../src/api-client/error'; +import { Route, RouteSectionProps, Router, useNavigate } from '@solidjs/router'; +import { createEffect } from 'solid-js'; +import { render, screen } from '@solidjs/testing-library'; +import { CreatePet } from '../../../../src/api-client/pet'; + +let mockCreatePet: typeof CreatePet; + +vi.mock('../../../../src/api-client/pet', () => { + return { + CreatePet: (pet: PetRequest) => { + return mockCreatePet(pet); + }, + }; +}); + +vi.mock('../../../../src/component/form/pet-form', () => { + return { + PetForm: (props: PetFormProps) => { + const onSubmit = () => { + props.submitPet({ name: 'Brownie', vaccinations: [] }); + }; + + return ( + List + + + + " + `); +}); + +test('network error', async () => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + mockCreatePet = async (_: PetRequest) => { + return new Promise((resolve) => resolve(new NetworkError({ title: 'network error' }))); + }; + + const App = (props: RouteSectionProps) => { + const navigate = useNavigate(); + + createEffect(() => { + navigate('/pet/create', { scroll: false }); + }); + + return
{props.children}
; + }; + + const { container } = render(() => ( + +
} /> + + + )); + + const testButton = await screen.findByTestId('test-button'); + + await userEvent.click(testButton); + + await screen.findByTestId('http-error'); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+
+
+

network error

+
+

+ Create Pet +

+ List +
+
+
+ " + `); +}); + +test('unprocessable entity', async () => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + mockCreatePet = async (_: PetRequest) => { + return new Promise((resolve) => + resolve(new UnprocessableEntity({ title: 'unprocessable entity' })), + ); + }; + + const App = (props: RouteSectionProps) => { + const navigate = useNavigate(); + + createEffect(() => { + navigate('/pet/create', { scroll: false }); + }); + + return
{props.children}
; + }; + + const { container } = render(() => ( + +
} /> + + + )); + + const testButton = await screen.findByTestId('test-button'); + + await userEvent.click(testButton); + + await screen.findByTestId('http-error'); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+
+
+

unprocessable entity

+
+

+ Create Pet +

+ List +
+
+
+ " + `); +}); + +test('successful', async () => { + mockCreatePet = async (petRequest: PetRequest) => { + const petResponse: PetResponse = { + id: '4d783b77-eb09-4603-b99b-f590b605eaa9', + createdAt: '2005-08-15T15:52:01+00:00', + ...petRequest, + }; + return new Promise((resolve) => resolve(petResponse)); + }; + + const App = (props: RouteSectionProps) => { + const navigate = useNavigate(); + + createEffect(() => { + navigate('/pet/create', { scroll: false }); + }); + + return
{props.children}
; + }; + + const { container } = render(() => ( + +
} /> +
} /> + + + )); + + const testButton = await screen.findByTestId('test-button'); + + await userEvent.click(testButton); + + await screen.findByTestId('page-pet-list'); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+
+ " + `); +}); diff --git a/tests/component/page/pet/read.test.tsx b/tests/component/page/pet/read.test.tsx new file mode 100644 index 0000000..713f3d5 --- /dev/null +++ b/tests/component/page/pet/read.test.tsx @@ -0,0 +1,148 @@ +/** @jsxImportSource solid-js */ + +import Read from '../../../../src/component/page/pet/read'; +import { vi } from 'vitest'; +import { test, expect } from 'vitest'; +import { formatHtml } from '../../../formatter'; +import { NotFound } from '../../../../src/api-client/error'; +import { Route, RouteSectionProps, Router, useNavigate } from '@solidjs/router'; +import { createEffect } from 'solid-js'; +import { render, screen } from '@solidjs/testing-library'; +import { PetResponse } from '../../../../src/model/model'; +import { ReadPet } from '../../../../src/api-client/pet'; + +let mockReadPet: typeof ReadPet; + +vi.mock('../../../../src/api-client/pet', () => { + return { + ReadPet: (id: string) => { + return mockReadPet(id); + }, + }; +}); + +test('not found', async () => { + mockReadPet = async (id: string) => { + expect(id).toBe('4d783b77-eb09-4603-b99b-f590b605eaa9'); + + return new Promise((resolve) => resolve(new NotFound({ title: 'title' }))); + }; + + const App = (props: RouteSectionProps) => { + const navigate = useNavigate(); + + createEffect(() => { + navigate('/pet/4d783b77-eb09-4603-b99b-f590b605eaa9', { scroll: false }); + }); + + return
{props.children}
; + }; + + const { container } = render(() => ( + +
} /> + + + )); + + await screen.findByTestId('page-pet-read'); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+
+
+

title

+
+

+ Read Pet +

+ List +
+
+
+ " + `); +}); + +test('success', async () => { + const pet: PetResponse = { + id: '4d783b77-eb09-4603-b99b-f590b605eaa9', + createdAt: '2005-08-15T15:52:01+00:00', + updatedAt: '2005-08-15T15:55:01+00:00', + name: 'Brownie', + tag: '0001-000', + vaccinations: [{ name: 'Rabies' }], + }; + + mockReadPet = async (id: string) => { + expect(id).toBe('4d783b77-eb09-4603-b99b-f590b605eaa9'); + + return new Promise((resolve) => resolve(pet)); + }; + + const App = (props: RouteSectionProps) => { + const navigate = useNavigate(); + + createEffect(() => { + navigate('/pet/4d783b77-eb09-4603-b99b-f590b605eaa9', { scroll: false }); + }); + + return
{props.children}
; + }; + + const { container } = render(() => ( + +
} /> + + + )); + + await screen.findByTestId('page-pet-read'); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+
+

+ Read Pet +

+
+
+
Id
+
4d783b77-eb09-4603-b99b-f590b605eaa9
+
CreatedAt
+
15.08.2005 - 17:52:01
+
UpdatedAt
+
15.08.2005 - 17:55:01
+
Name
+
Brownie
+
Tag
+
0001-000
+
Vaccinations
+
+
    +
  • Rabies
  • +
+
+
+
+ List +
+
+
+ " + `); +}); diff --git a/tests/component/page/pet/update.test.tsx b/tests/component/page/pet/update.test.tsx new file mode 100644 index 0000000..a1458d8 --- /dev/null +++ b/tests/component/page/pet/update.test.tsx @@ -0,0 +1,364 @@ +/** @jsxImportSource solid-js */ + +import Update from '../../../../src/component/page/pet/update'; +import { PetFormProps } from '../../../../src/component/form/pet-form'; +import { vi } from 'vitest'; +import { test, expect } from 'vitest'; +import { PetRequest, PetResponse } from '../../../../src/model/model'; +import { formatHtml } from '../../../formatter'; +import { NetworkError, NotFound, UnprocessableEntity } from '../../../../src/api-client/error'; +import { Route, RouteSectionProps, Router, useNavigate } from '@solidjs/router'; +import { createEffect } from 'solid-js'; +import { render, screen } from '@solidjs/testing-library'; +import { ReadPet, UpdatePet } from '../../../../src/api-client/pet'; +import userEvent from '@testing-library/user-event'; + +let mockReadPet: typeof ReadPet; +let mockUpdatePet: typeof UpdatePet; + +vi.mock('../../../../src/api-client/pet', () => { + return { + ReadPet: (id: string) => { + return mockReadPet(id); + }, + UpdatePet: (id: string, pet: PetRequest) => { + return mockUpdatePet(id, pet); + }, + }; +}); + +vi.mock('../../../../src/component/form/pet-form', () => { + return { + PetForm: (props: PetFormProps) => { + const onSubmit = () => { + props.submitPet({ name: 'Brownie', vaccinations: [] }); + }; + + return ( + List +
+
+
+ " + `); +}); + +test('network error', async () => { + const pet: PetResponse = { + id: '4d783b77-eb09-4603-b99b-f590b605eaa9', + createdAt: '2005-08-15T15:52:01+00:00', + updatedAt: '2005-08-15T15:55:01+00:00', + name: 'Brownie', + tag: '0001-000', + vaccinations: [{ name: 'Rabies' }], + }; + + mockReadPet = async (id: string) => { + expect(id).toBe('4d783b77-eb09-4603-b99b-f590b605eaa9'); + + return new Promise((resolve) => resolve(pet)); + }; + + mockUpdatePet = async (id: string) => { + expect(id).toBe('4d783b77-eb09-4603-b99b-f590b605eaa9'); + + return new Promise((resolve) => resolve(new NetworkError({ title: 'network error' }))); + }; + + const App = (props: RouteSectionProps) => { + const navigate = useNavigate(); + + createEffect(() => { + navigate('/pet/4d783b77-eb09-4603-b99b-f590b605eaa9/update', { scroll: false }); + }); + + return
{props.children}
; + }; + + const { container } = render(() => ( + +
} /> + + + )); + + const testButton = await screen.findByTestId('test-button'); + + await userEvent.click(testButton); + + await screen.findByTestId('http-error'); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+
+
+

network error

+
+

+ Pet Update +

+ List +
+
+
+ " + `); +}); + +test('unprocessable entity', async () => { + const pet: PetResponse = { + id: '4d783b77-eb09-4603-b99b-f590b605eaa9', + createdAt: '2005-08-15T15:52:01+00:00', + updatedAt: '2005-08-15T15:55:01+00:00', + name: 'Brownie', + tag: '0001-000', + vaccinations: [{ name: 'Rabies' }], + }; + + mockReadPet = async (id: string) => { + expect(id).toBe('4d783b77-eb09-4603-b99b-f590b605eaa9'); + + return new Promise((resolve) => resolve(pet)); + }; + + mockUpdatePet = async (id: string) => { + expect(id).toBe('4d783b77-eb09-4603-b99b-f590b605eaa9'); + + return new Promise((resolve) => + resolve(new UnprocessableEntity({ title: 'unprocessable entity' })), + ); + }; + + const App = (props: RouteSectionProps) => { + const navigate = useNavigate(); + + createEffect(() => { + navigate('/pet/4d783b77-eb09-4603-b99b-f590b605eaa9/update', { scroll: false }); + }); + + return
{props.children}
; + }; + + const { container } = render(() => ( + +
} /> + + + )); + + const testButton = await screen.findByTestId('test-button'); + + await userEvent.click(testButton); + + await screen.findByTestId('http-error'); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+
+
+

unprocessable entity

+
+

+ Pet Update +

+ List +
+
+
+ " + `); +}); + +test('successful', async () => { + const pet: PetResponse = { + id: '4d783b77-eb09-4603-b99b-f590b605eaa9', + createdAt: '2005-08-15T15:52:01+00:00', + updatedAt: '2005-08-15T15:55:01+00:00', + name: 'Brownie', + tag: '0001-000', + vaccinations: [{ name: 'Rabies' }], + }; + + mockReadPet = async (id: string) => { + expect(id).toBe('4d783b77-eb09-4603-b99b-f590b605eaa9'); + + return new Promise((resolve) => resolve(pet)); + }; + + mockUpdatePet = async (id: string, petRequest: PetRequest) => { + expect(id).toBe('4d783b77-eb09-4603-b99b-f590b605eaa9'); + + const petResponse: PetResponse = { + id: '4d783b77-eb09-4603-b99b-f590b605eaa9', + createdAt: '2005-08-15T15:52:01+00:00', + updatedAt: '2005-08-15T15:52:01+00:00', + ...petRequest, + }; + return new Promise((resolve) => resolve(petResponse)); + }; + + const App = (props: RouteSectionProps) => { + const navigate = useNavigate(); + + createEffect(() => { + navigate('/pet/4d783b77-eb09-4603-b99b-f590b605eaa9/update', { scroll: false }); + }); + + return
{props.children}
; + }; + + const { container } = render(() => ( + +
} /> +
} /> + + + )); + + const testButton = await screen.findByTestId('test-button'); + + await userEvent.click(testButton); + + await screen.findByTestId('page-pet-list'); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+
+ " + `); +}); diff --git a/tests/component/partial/http-error.test.tsx b/tests/component/partial/http-error.test.tsx new file mode 100644 index 0000000..0c68368 --- /dev/null +++ b/tests/component/partial/http-error.test.tsx @@ -0,0 +1,49 @@ +/** @jsxImportSource solid-js */ + +import { HttpError as HttpErrorPartial } from '../../../src/component/partial/http-error'; +import { test, expect } from 'vitest'; +import { formatHtml } from '../../formatter'; +import { HttpError, BadRequestOrUnprocessableEntity } from '../../../src/api-client/error'; +import { render } from '@solidjs/testing-library'; + +test('minimal', () => { + const httpError = new HttpError({ + title: 'This is the title', + }); + + const { container } = render(() => ); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+

This is the title

+
+
+ " + `); +}); + +test('maximal', () => { + const httpError = new BadRequestOrUnprocessableEntity({ + title: 'This is the title', + detail: 'This is the detail', + instance: 'This is the instance', + invalidParameters: [{ name: 'Invalid Parameter Name', reason: 'Invalid Parameter Reason' }], + }); + + const { container } = render(() => ); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+

This is the title

+

This is the detail

+

This is the instance

+
    +
  • Invalid Parameter Name: Invalid Parameter Reason
  • +
+
+
+ " + `); +}); diff --git a/tests/component/partial/pagination.test.tsx b/tests/component/partial/pagination.test.tsx new file mode 100644 index 0000000..b8e55f4 --- /dev/null +++ b/tests/component/partial/pagination.test.tsx @@ -0,0 +1,323 @@ +/** @jsxImportSource solid-js */ + +import { render, screen } from '@solidjs/testing-library'; +import userEvent from '@testing-library/user-event'; +import { test, expect } from 'vitest'; +import { formatHtml } from '../../formatter'; +import { Pagination } from '../../../src/component/partial/pagination'; + +test('max pages 1', () => { + const submitPage = (): void => {}; + + const { container } = render(() => ( + 1} getMaxPages={() => 1} getTotalPages={() => 10} submitPage={submitPage} /> + )); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+ " + `); +}); + +test('total pages 1', () => { + const submitPage = (): void => {}; + + const { container } = render(() => ( + 1} getMaxPages={() => 7} getTotalPages={() => 1} submitPage={submitPage} /> + )); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+ " + `); +}); + +test('current 1', () => { + const submitPage = (): void => {}; + + const { container } = render(() => ( + 1} getMaxPages={() => 7} getTotalPages={() => 10} submitPage={submitPage} /> + )); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+
+ " + `); +}); + +test('current 4', () => { + const submitPage = (): void => {}; + + const { container } = render(() => ( + 4} getMaxPages={() => 7} getTotalPages={() => 10} submitPage={submitPage} /> + )); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+
+ " + `); +}); + +test('current 7', () => { + const submitPage = (): void => {}; + + const { container } = render(() => ( + 7} getMaxPages={() => 7} getTotalPages={() => 10} submitPage={submitPage} /> + )); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+
+ " + `); +}); + +test('current 10', () => { + const submitPage = (): void => {}; + + const { container } = render(() => ( + 10} getMaxPages={() => 7} getTotalPages={() => 10} submitPage={submitPage} /> + )); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+
+ " + `); +}); + +test('buttons', async () => { + const pages: number[] = []; + + const submitPage = (page: number): void => { + pages.push(page); + }; + + render(() => ( + 7} getMaxPages={() => 7} getTotalPages={() => 10} submitPage={submitPage} /> + )); + + for await (const element of screen.getAllByRole('button')) { + await userEvent.click(element); + } + + expect(pages).toEqual([1, 6, 4, 5, 6, 7, 8, 9, 10, 8, 10]); +}); diff --git a/tests/denormalizer/invalid-parameter-by-name-denormalizer.test.ts b/tests/denormalizer/invalid-parameter-by-name-denormalizer.test.ts new file mode 100644 index 0000000..14be9d5 --- /dev/null +++ b/tests/denormalizer/invalid-parameter-by-name-denormalizer.test.ts @@ -0,0 +1,32 @@ +import { InvalidParameter } from '../../src/api-client/error'; +import InvalidParameterByNameDenormalizer from '../../src/denormalizer/invalid-parameter-by-name-denormalizer'; +import { test, expect } from 'vitest'; + +test('default', () => { + const invalidParameters: Array = [ + { name: 'name', reason: 'wrong type', details: { key: 'value1' } }, + { name: 'name', reason: 'not empty', details: { key: 'value2' } }, + { name: 'description', reason: 'to long', details: { key: 'value3' } }, + ]; + + const invalidParameterByName = InvalidParameterByNameDenormalizer(invalidParameters); + + expect(invalidParameterByName.has('name')).toBeTruthy(); + + const InvalidParametersOfName = invalidParameterByName.get('name'); + + expect(InvalidParametersOfName).toBeInstanceOf(Array); + expect(InvalidParametersOfName).toHaveLength(2); + + expect(InvalidParametersOfName instanceof Array ? InvalidParametersOfName[0] : null).toBe(invalidParameters[0]); + expect(InvalidParametersOfName instanceof Array ? InvalidParametersOfName[1] : null).toBe(invalidParameters[1]); + + const InvalidParametersOfDescription = invalidParameterByName.get('description'); + + expect(InvalidParametersOfDescription).toBeInstanceOf(Array); + expect(InvalidParametersOfDescription).toHaveLength(1); + + expect(InvalidParametersOfDescription instanceof Array ? InvalidParametersOfDescription[0] : null).toBe( + invalidParameters[2], + ); +}); diff --git a/tests/formatter.ts b/tests/formatter.ts new file mode 100644 index 0000000..4d57bb9 --- /dev/null +++ b/tests/formatter.ts @@ -0,0 +1,5 @@ +import { format } from 'prettier'; + +export const formatHtml = (html: string) => { + return format(html, { parser: 'html' }); +}; diff --git a/tests/routes.test.tsx b/tests/routes.test.tsx new file mode 100644 index 0000000..a6d0424 --- /dev/null +++ b/tests/routes.test.tsx @@ -0,0 +1,207 @@ +/** @jsxImportSource solid-js */ + +import { test, expect } from 'vitest'; +import { formatHtml } from './formatter'; +import { render, screen } from '@solidjs/testing-library'; +import Routes from '../src/routes'; +import { vi } from 'vitest'; +import { RouteSectionProps, Router, useNavigate } from '@solidjs/router'; +import { createEffect } from 'solid-js'; + +vi.mock('../src/component/page/home', () => { + return { + default: () =>
, + }; +}); + +vi.mock('../src/component/page/pet/list', () => { + return { + default: () =>
, + }; +}); + +vi.mock('../src/component/page/pet/create', () => { + return { + default: () =>
, + }; +}); + +vi.mock('../src/component/page/pet/read', () => { + return { + default: () =>
, + }; +}); + +vi.mock('../src/component/page/pet/update', () => { + return { + default: () =>
, + }; +}); + +vi.mock('../src/component/page/not-found', () => { + return { + default: () =>
, + }; +}); + +test('home page', async () => { + const App = (props: RouteSectionProps) => { + const navigate = useNavigate(); + + createEffect(() => { + navigate('/', { scroll: false }); + }); + + return
{props.children}
; + }; + + const { container } = render(() => ( + + + + )); + + await screen.findByTestId('page-home-mock'); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+
+ " + `); +}); + +test('not found', async () => { + const App = (props: RouteSectionProps) => { + const navigate = useNavigate(); + + createEffect(() => { + navigate('/some-unknown-page', { scroll: false }); + }); + + return
{props.children}
; + }; + + const { container } = render(() => ( + + + + )); + + await screen.findByTestId('page-not-found-mock'); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+
+ " + `); +}); + +test('pet list', async () => { + const App = (props: RouteSectionProps) => { + const navigate = useNavigate(); + + createEffect(() => { + navigate('/pet', { scroll: false }); + }); + + return
{props.children}
; + }; + + const { container } = render(() => ( + + + + )); + + await screen.findByTestId('page-pet-list-mock'); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+
+ " + `); +}); + +test('pet create', async () => { + const App = (props: RouteSectionProps) => { + const navigate = useNavigate(); + + createEffect(() => { + navigate('/pet/create', { scroll: false }); + }); + + return
{props.children}
; + }; + + const { container } = render(() => ( + + + + )); + + await screen.findByTestId('page-pet-create-mock'); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+
+ " + `); +}); + +test('pet read', async () => { + const App = (props: RouteSectionProps) => { + const navigate = useNavigate(); + + createEffect(() => { + navigate('/pet/4d783b77-eb09-4603-b99b-f590b605eaa9', { scroll: false }); + }); + + return
{props.children}
; + }; + + const { container } = render(() => ( + + + + )); + + await screen.findByTestId('page-pet-read-mock'); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+
+ " + `); +}); + +test('pet update', async () => { + const App = (props: RouteSectionProps) => { + const navigate = useNavigate(); + + createEffect(() => { + navigate('/pet/4d783b77-eb09-4603-b99b-f590b605eaa9/update', { scroll: false }); + }); + + return
{props.children}
; + }; + + const { container } = render(() => ( + + + + )); + + await screen.findByTestId('page-pet-update-mock'); + + expect(formatHtml(container.outerHTML)).toMatchInlineSnapshot(` + "
+
+
+ " + `); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..3999958 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "preserve", + "jsxImportSource": "solid-js", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..97ede7e --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "strict": true + }, + "include": ["vite.config.ts"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..c13d746 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,23 @@ +/// +/// + +import { defineConfig } from 'vite' +import solid from 'vite-plugin-solid' + +export default defineConfig({ + plugins: [solid()], + test: { + globals: true, + environment: "jsdom", + setupFiles: "./vitest.setup.ts", + include: ['tests/**/*.test.*'], + coverage: { + all: true, + clean: true, + reporter: ['text', 'html', 'lcov'], + provider: 'v8', + include: ['src'], + exclude: ['src/index.tsx', 'src/vite-env.d.ts'], + } + }, +}) diff --git a/vitest.setup.ts b/vitest.setup.ts new file mode 100644 index 0000000..7b0828b --- /dev/null +++ b/vitest.setup.ts @@ -0,0 +1 @@ +import '@testing-library/jest-dom';