diff --git a/.github/workflows/backend-dev.yml b/.github/workflows/backend-dev.yml new file mode 100644 index 000000000..a3257f028 --- /dev/null +++ b/.github/workflows/backend-dev.yml @@ -0,0 +1,72 @@ +name: backend-push + +on: + push: + branches: [ "be-dev" ] + +jobs: + build: + runs-on: [ self-hosted, backend-dev ] + + defaults: + run: + shell: bash + working-directory: ./server + + permissions: + contents: read + + steps: + - name: CheckOut + uses: actions/checkout@v4 + with: + token: ${{secrets.CONFIG_SUBMODULE_TOKEN}} + submodules: true + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Test with Gradle Wrapper + run: ./gradlew clean build + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Set up Docker BuildX + uses: docker/setup-buildx-action@v3 + + - name: Build and push + run: | + docker buildx build --platform linux/arm64 -t \ + ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_DEV }} --push . + + deploy: + needs: build + runs-on: [ self-hosted, backend-dev ] + steps: + - name: Docker remove + run: | + CONTAINER_IDS=$(sudo docker ps -qa) + if [ -n "$CONTAINER_IDS" ]; then + sudo docker rm -f $CONTAINER_IDS + else + echo "No running containers found." + fi + + - name: Docker Image pull + run: sudo docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_DEV }} + + - name: Docker run + run: sudo docker run -d -p 8080:8080 -e SPRING_PROFILES_ACTIVE=dev -v log-volume:/app/logs --name haengdong-backend ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_DEV }} diff --git a/.github/workflows/backend-prod.yml b/.github/workflows/backend-prod.yml new file mode 100644 index 000000000..f7daacd33 --- /dev/null +++ b/.github/workflows/backend-prod.yml @@ -0,0 +1,74 @@ +name: backend-push + +on: + push: + branches: [ "main" ] + paths: + - 'server/**' + +jobs: + build: + runs-on: ubuntu-latest + + defaults: + run: + shell: bash + working-directory: ./server + + permissions: + contents: read + + steps: + - name: CheckOut + uses: actions/checkout@v4 + with: + token: ${{secrets.CONFIG_SUBMODULE_TOKEN}} + submodules: true + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Test with Gradle Wrapper + run: ./gradlew clean build + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Set up Docker BuildX + uses: docker/setup-buildx-action@v3 + + - name: Build and push + run: | + docker buildx build --platform linux/arm64 -t \ + ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_PROD }} --push . + + deploy: + needs: build + runs-on: [ self-hosted, backend-prod ] + steps: + - name: Docker remove + run: | + CONTAINER_IDS=$(sudo docker ps -qa) + if [ -n "$CONTAINER_IDS" ]; then + sudo docker rm -f $CONTAINER_IDS + else + echo "No running containers found." + fi + + - name: Docker Image pull + run: sudo docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_PROD }} + + - name: Docker run + run: sudo docker run -d -p 8080:8080 -e SPRING_PROFILES_ACTIVE=prod -v log-volume:/app/logs --name haengdong-backend ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_PROD }} diff --git a/.github/workflows/backend-pull-request.yml b/.github/workflows/backend-pull-request.yml new file mode 100644 index 000000000..df008fd97 --- /dev/null +++ b/.github/workflows/backend-pull-request.yml @@ -0,0 +1,44 @@ +name: backend-pull-request + +on: + pull_request: + branches: [ "main", "be-dev" ] + +jobs: + build: + runs-on: [ ubuntu-latest ] + + defaults: + run: + working-directory: ./server + + steps: + - name: CheckOut + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Test with Gradle Wrapper + run: ./gradlew clean build + + - name: publish unit test results + uses: EnricoMi/publish-unit-test-result-action@v2 + if: always() + with: + files: server/build/test-results/test/TEST-*.xml + + - name: add comments to a pull request + uses: mikepenz/action-junit-report@v3 + if: always() + with: + report_paths: server/build/test-results/test/TEST-*.xml diff --git a/.github/workflows/design-pull-request.yml b/.github/workflows/design-pull-request.yml new file mode 100644 index 000000000..af168a976 --- /dev/null +++ b/.github/workflows/design-pull-request.yml @@ -0,0 +1,54 @@ +name: Storybook Deployment + +on: + pull_request: + branches: + - fe-dev + paths: + - 'HDesign/**' + +jobs: + chromatic: + name: Run Chromatic + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.15.1' + + - name: Cache dependencies + id: cache + uses: actions/cache@v3 + with: + path: '**/node_modules' + key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-npm- + + - name: Install dependencies + if: steps.cache.outputs.cache-hit != 'true' + run: | + cd HDesign + npm install + + - name: Run lint + run: npm run lint + working-directory: ./HDesign + + - name: Run Chromatic + uses: chromaui/action@latest + id: publish_chromatic + with: + workingDir: HDesign + projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} + + - name: Comment on PR + uses: thollander/actions-comment-pull-request@v2 + with: + message: '๐Ÿš€ **storybook**: ${{ steps.publish_chromatic.outputs.storybookUrl }}' diff --git a/.github/workflows/frontend-pull-request.yml b/.github/workflows/frontend-pull-request.yml new file mode 100644 index 000000000..c2749939b --- /dev/null +++ b/.github/workflows/frontend-pull-request.yml @@ -0,0 +1,49 @@ +name: frontend-pull-request + +on: + pull_request: + types: [opened, synchronize] + branches: [main, fe-dev] + paths: + - 'client/**' + +jobs: + test: + runs-on: ubuntu-latest + + defaults: + run: + shell: bash + working-directory: ./client + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.15.1' + + - name: Install dependencies + working-directory: ./client + run: npm install + + - name: Run lint + working-directory: ./client + run: npm run lint + + - name: Run test + working-directory: ./client + run: npm run test + + - name: Cypress test + run: npm run dev & + env: + CI: true + + - name: Wait for the server to start + run: sleep 3 + + - name: Run Cypress tests + run: npm run cypress-run diff --git a/.github/workflows/pr-issue-close.yml b/.github/workflows/pr-issue-close.yml new file mode 100644 index 000000000..c37eb255d --- /dev/null +++ b/.github/workflows/pr-issue-close.yml @@ -0,0 +1,33 @@ +name: Close Issue on PR Merge + +on: + pull_request: + types: [closed] + +jobs: + close-issue: + if: github.event.pull_request.merged == true + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Extract issue number from PR body + id: extract_issue + run: | + # Fetch PR body + PR_BODY=$(curl -s -H "Authorization: token ${{ secrets.CONFIG_SUBMODULE_TOKEN }}" \ + "https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}" \ + | jq -r '.body') + # Extract issue number from PR body using regex (customize if needed) + ISSUE_NUMBER=$(echo "$PR_BODY" | grep -oP '#\d+' | head -1 | sed 's/#//') + echo "ISSUE_NUMBER=$ISSUE_NUMBER" >> $GITHUB_ENV + - name: Close associated issue + if: env.ISSUE_NUMBER != '' + run: | + echo "Closing issue #${{ env.ISSUE_NUMBER }}" + curl -s -X PATCH -H "Authorization: token ${{ secrets.CONFIG_SUBMODULE_TOKEN }}" \ + -H "Accept: application/vnd.github.v3+json" \ + -d '{"state": "closed"}' \ + "https://api.github.com/repos/${{ github.repository }}/issues/${{ env.ISSUE_NUMBER }}" diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..d013a93bc --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "server/src/main/resources/config"] + branch = main + path = server/src/main/resources/config + url = https://github.com/woowacourse-teams/2024-haeng-dong-config.git diff --git a/HDesign/.gitignore b/HDesign/.gitignore new file mode 100644 index 000000000..b98928456 --- /dev/null +++ b/HDesign/.gitignore @@ -0,0 +1,12 @@ +logs +*.log +npm-debug.log* + +node_modules +dist + +.env + +storybook-static +*storybook.log +.DS_Store diff --git a/HDesign/.npmignore b/HDesign/.npmignore new file mode 100644 index 000000000..363c89306 --- /dev/null +++ b/HDesign/.npmignore @@ -0,0 +1,7 @@ +node_modules/ +src/ +tsconfig.json +.storybook/ +.eslintrc.json +.prettierrc +webpack.config.js \ No newline at end of file diff --git a/HDesign/.npmrc b/HDesign/.npmrc new file mode 100644 index 000000000..ece05f588 --- /dev/null +++ b/HDesign/.npmrc @@ -0,0 +1,2 @@ +engine-strict = true +legacy-peer-deps = true diff --git a/HDesign/.prettierrc b/HDesign/.prettierrc new file mode 100644 index 000000000..c025201f4 --- /dev/null +++ b/HDesign/.prettierrc @@ -0,0 +1,12 @@ +{ + "singleQuote": true, + "trailingComma": "all", + "printWidth": 120, + "tabWidth": 2, + "semi": true, + "arrowParens": "avoid", + "endOfLine": "auto", + "jsxSingleQuote": false, + "bracketSpacing": false, + "proseWrap": "preserve" +} diff --git a/HDesign/.storybook/main.ts b/HDesign/.storybook/main.ts new file mode 100644 index 000000000..a1fa61591 --- /dev/null +++ b/HDesign/.storybook/main.ts @@ -0,0 +1,47 @@ +/** @type { import('@storybook/react-webpack5').StorybookConfig } */ +import type {StorybookConfig} from '@storybook/react-webpack5'; +import path from 'path'; + +const config: StorybookConfig = { + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], + addons: [ + '@storybook/addon-webpack5-compiler-swc', + '@storybook/addon-onboarding', + '@storybook/addon-links', + '@storybook/addon-essentials', + '@chromatic-com/storybook', + '@storybook/addon-interactions', + ], + framework: { + name: '@storybook/react-webpack5', + options: {}, + }, + webpackFinal: async config => { + if (config.resolve) { + config.resolve.alias = { + ...config.resolve.alias, + '@components': path.resolve(__dirname, '../src/components'), + '@token': path.resolve(__dirname, '../src/token'), + '@type': path.resolve(__dirname, '../src/type'), + '@theme': path.resolve(__dirname, '../src/theme'), + '@assets': path.resolve(__dirname, '../src/assets'), + '@utils': path.resolve(__dirname, '../src/utils'), + }; + } + + config.module = config.module || {}; + config.module.rules = config.module.rules || []; + + const imageRule = config.module.rules.find(rule => rule?.['test']?.test('.svg')); + if (imageRule) { + imageRule['exclude'] = /\.svg$/; + } + + config.module.rules.push({ + test: /\.svg$/, + use: ['@svgr/webpack'], + }); + return config; + }, +}; +export default config; diff --git a/HDesign/.storybook/preview.tsx b/HDesign/.storybook/preview.tsx new file mode 100644 index 000000000..22008ad03 --- /dev/null +++ b/HDesign/.storybook/preview.tsx @@ -0,0 +1,41 @@ +/** @jsxImportSource @emotion/react */ + +import type {Preview} from '@storybook/react'; +import {HDesignProvider} from '../src/theme/HDesignProvider'; + +const preview: Preview = { + parameters: { + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i, + }, + }, + viewport: { + defaultViewport: { + styles: { + width: '375px', + height: '812px', + }, + }, + }, + backgrounds: { + default: 'gray', + values: [ + { + name: 'gray', + value: '#f3f3f3', + }, + ], + }, + }, + decorators: [ + Story => ( + + + + ), + ], +}; + +export default preview; diff --git a/HDesign/eslint.config.mjs b/HDesign/eslint.config.mjs new file mode 100644 index 000000000..e025936a4 --- /dev/null +++ b/HDesign/eslint.config.mjs @@ -0,0 +1,153 @@ +import path from 'node:path'; +import {fileURLToPath} from 'node:url'; + +import {fixupConfigRules, fixupPluginRules} from '@eslint/compat'; +import react from 'eslint-plugin-react'; +import typescriptEslint from '@typescript-eslint/eslint-plugin'; +import _import from 'eslint-plugin-import'; +import prettier from 'eslint-plugin-prettier'; +import tsParser from '@typescript-eslint/parser'; +import js from '@eslint/js'; +import {FlatCompat} from '@eslint/eslintrc'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all, +}); + +export default [ + ...fixupConfigRules( + compat.extends( + 'eslint:recommended', + 'plugin:react/recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:react-hooks/recommended', + 'plugin:import/typescript', + 'plugin:import/recommended', + 'plugin:import/errors', + 'plugin:import/warnings', + 'prettier', + 'plugin:prettier/recommended', + ), + ), + { + plugins: { + react: fixupPluginRules(react), + '@typescript-eslint': fixupPluginRules(typescriptEslint), + import: fixupPluginRules(_import), + prettier: fixupPluginRules(prettier), + }, + + languageOptions: { + parser: tsParser, + }, + + settings: { + 'import/resolver': { + node: { + extensions: ['.js', '.jsx', '.ts', '.tsx'], + }, + + typescript: { + directory: './lib', + }, + }, + + 'import/parsers': { + '@typescript-eslint/parser': ['.ts', '.tsx'], + }, + + 'import/ignore': ['lottie-react'], + }, + + rules: { + 'no-use-before-define': 0, + 'prettier/prettier': 'error', + 'react/react-in-jsx-scope': 'off', + 'react/prop-types': 'off', + 'import/prefer-default-export': 0, + 'import/no-named-as-default': 0, + 'import/namespace': 0, + 'import/extensions': 0, + 'import/no-cycle': 0, + 'react/no-unknown-property': 0, + 'react/jsx-filename-extension': [1, {extensions: ['.ts', '.tsx']}], + 'react/function-component-definition': 0, + 'react/jsx-props-no-spreading': 0, + 'react/jsx-key': 0, + 'react/button-has-type': 'off', + 'no-shadow': 0, + 'no-console': 0, + 'no-alert': 0, + 'react/no-children-prop': 'off', + 'react/no-array-index-key': 'off', + 'react-hooks/exhaustive-deps': 'off', + 'react-hooks/rules-of-hooks': 'off', + 'react/jsx-no-useless-fragment': 'off', + 'react/jsx-no-constructed-context-values': 'off', + 'jsx-a11y/click-events-have-key-events': 'off', + 'jsx-a11y/no-static-element-interactions': 'off', + + '@typescript-eslint/no-unused-vars': 0, + + // 'react/jsx-uses-vars': 'error', + // '@typescript-eslint/no-use-before-define': ['error'], + // '@typescript-eslint/explicit-module-boundary-types': 'error', + + 'import/order': [ + 'error', + { + 'newlines-between': 'always', + + groups: ['type', 'builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'unknown'], + + pathGroups: [ + { + pattern: 'react*', + group: 'external', + position: 'before', + }, + { + pattern: '@components/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@layouts/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@assets/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@theme/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@token/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@types/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@utils/*', + group: 'internal', + position: 'after', + }, + ], + }, + ], + }, + }, +]; diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json new file mode 100644 index 000000000..fb92d2ae1 --- /dev/null +++ b/HDesign/package-lock.json @@ -0,0 +1,13707 @@ +{ + "name": "haengdong-design", + "version": "0.1.81", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "haengdong-design", + "version": "0.1.81", + "license": "ISC", + "dependencies": { + "@emotion/react": "^11.11.4", + "@storybook/addon-webpack5-compiler-swc": "^1.0.5", + "@svgr/webpack": "^8.1.0", + "lottie-react": "^2.4.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.24.1" + }, + "devDependencies": { + "@chromatic-com/storybook": "^1.6.1", + "@eslint/compat": "^1.1.0", + "@eslint/js": "^9.6.0", + "@storybook/addon-essentials": "^8.2.2", + "@storybook/addon-interactions": "^8.2.2", + "@storybook/addon-links": "^8.2.2", + "@storybook/addon-onboarding": "^8.2.2", + "@storybook/blocks": "^8.2.2", + "@storybook/react": "^8.2.2", + "@storybook/react-webpack5": "^8.2.3", + "@storybook/test": "^8.2.2", + "@swc/core": "^1.7.6", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "esbuild": "^0.23.0", + "eslint": "^9.8.0", + "eslint-config-prettier": "^9.1.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-jsx-a11y": "^6.9.0", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-react": "^7.34.4", + "eslint-plugin-react-hooks": "^4.6.2", + "eslint-plugin-storybook": "^0.8.0", + "file-loader": "^6.2.0", + "globals": "^15.8.0", + "prettier": "3.3.2", + "storybook": "^8.2.2", + "storybook-addon-react-router-v6": "^2.0.15", + "ts-loader": "^9.5.1", + "tsc-alias": "^1.8.10", + "typescript": "^5.5.3", + "typescript-eslint": "^7.16.0" + }, + "engines": { + "node": ">=20.15.1", + "npm": ">=10.7.0" + } + }, + "node_modules/@adobe/css-tools": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", + "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==", + "dev": true + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.9.tgz", + "integrity": "sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz", + "integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.9", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-module-transforms": "^7.24.9", + "@babel/helpers": "^7.24.8", + "@babel/parser": "^7.24.8", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.9", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/@babel/core/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.9.tgz", + "integrity": "sha512-G8v3jRg+z8IwY1jHFxvCNhOPYPterE4XljNgdGTYfSTtzzwjIswIzIaSPSLs3R7yFuqnqNeay5rjICfqVr+/6A==", + "dependencies": { + "@babel/types": "^7.24.9", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", + "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz", + "integrity": "sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==", + "dependencies": { + "@babel/compat-data": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.8.tgz", + "integrity": "sha512-4f6Oqnmyp2PP3olgUMmOwC3akxSm5aBYraQ6YDdKy7NcAMkDECHWG0DEnV6M2UAkERgIBhYt8S27rURPg7SxWA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz", + "integrity": "sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", + "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", + "dependencies": { + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", + "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", + "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "dependencies": { + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz", + "integrity": "sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz", + "integrity": "sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-wrap-function": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", + "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.7", + "@babel/helper-optimise-call-expression": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz", + "integrity": "sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==", + "dependencies": { + "@babel/helper-function-name": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.8.tgz", + "integrity": "sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==", + "dependencies": { + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", + "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz", + "integrity": "sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz", + "integrity": "sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", + "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz", + "integrity": "sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.7.tgz", + "integrity": "sha512-9G8GYT/dxn/D1IIKOUBmGX0mnmj46mGH9NnZyJLwtCpgh5f7D2VbuKodb+2s9m1Yavh1s7ASQN8lf0eqrb1LTw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", + "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", + "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", + "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", + "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", + "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz", + "integrity": "sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", + "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", + "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz", + "integrity": "sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", + "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", + "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.8.tgz", + "integrity": "sha512-VXy91c47uujj758ud9wx+OMgheXm4qJfyhj1P18YvlrQkNOSrwsteHk+EFS3OMGfhMhpZa0A+81eE7G4QC+3CA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", + "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/template": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", + "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", + "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", + "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", + "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", + "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", + "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.24.7.tgz", + "integrity": "sha512-cjRKJ7FobOH2eakx7Ja+KpJRj8+y+/SiB3ooYm/n2UJfxu0oEaOoxOinitkJcPqv9KxS0kxTGPUaR7L2XcXDXA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-flow": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", + "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz", + "integrity": "sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", + "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz", + "integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", + "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", + "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", + "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", + "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-simple-access": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz", + "integrity": "sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==", + "dependencies": { + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", + "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", + "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", + "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", + "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", + "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", + "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", + "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", + "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", + "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", + "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", + "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", + "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.24.7.tgz", + "integrity": "sha512-7LidzZfUXyfZ8/buRW6qIIHBY8wAZ1OrY9c/wTr8YhZ6vMPo+Uc/CVFLYY1spZrEQlD4w5u8wjqk5NQ3OVqQKA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", + "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz", + "integrity": "sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", + "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz", + "integrity": "sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", + "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", + "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", + "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", + "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", + "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", + "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", + "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.8.tgz", + "integrity": "sha512-CgFgtN61BbdOGCP4fLaAMOPkzWUh6yQZNMr5YSt8uz2cZSSiQONCQFWqsE4NeVfOIhqDOlS9CR3WD91FzMeB2Q==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/plugin-syntax-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", + "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", + "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", + "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", + "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.8.tgz", + "integrity": "sha512-vObvMZB6hNWuDxhSaEPTKCwcqkAIuDtE+bQGn4XMXne1DSLzFVY8Vmj1bm+mUQXYNN8NmaQEO+r8MMbzPr1jBQ==", + "dependencies": { + "@babel/compat-data": "^7.24.8", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.24.7", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.24.7", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoped-functions": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.24.7", + "@babel/plugin-transform-class-properties": "^7.24.7", + "@babel/plugin-transform-class-static-block": "^7.24.7", + "@babel/plugin-transform-classes": "^7.24.8", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-dotall-regex": "^7.24.7", + "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-dynamic-import": "^7.24.7", + "@babel/plugin-transform-exponentiation-operator": "^7.24.7", + "@babel/plugin-transform-export-namespace-from": "^7.24.7", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.24.7", + "@babel/plugin-transform-json-strings": "^7.24.7", + "@babel/plugin-transform-literals": "^7.24.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-member-expression-literals": "^7.24.7", + "@babel/plugin-transform-modules-amd": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-modules-systemjs": "^7.24.7", + "@babel/plugin-transform-modules-umd": "^7.24.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-new-target": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-object-super": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-property-literals": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-reserved-words": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-template-literals": "^7.24.7", + "@babel/plugin-transform-typeof-symbol": "^7.24.8", + "@babel/plugin-transform-unicode-escapes": "^7.24.7", + "@babel/plugin-transform-unicode-property-regex": "^7.24.7", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.37.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-flow": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.24.7.tgz", + "integrity": "sha512-NL3Lo0NorCU607zU3NwRyJbpaB6E3t0xtd3LfAQKDfkeX4/ggcDXvkmkW42QWT5owUeW/jAe4hn+2qvkV1IbfQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-transform-flow-strip-types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", + "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.24.7", + "@babel/plugin-transform-react-jsx-development": "^7.24.7", + "@babel/plugin-transform-react-pure-annotations": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", + "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.24.6.tgz", + "integrity": "sha512-WSuFCc2wCqMeXkz/i3yfAAsxwWflEgbVkZzivgAmXl/MxrXeoYFZOOPllbC8R8WTF7u61wSRQtDVZ1879cdu6w==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.6", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/register/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + }, + "node_modules/@babel/runtime": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", + "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", + "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.8.tgz", + "integrity": "sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.8", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/parser": "^7.24.8", + "@babel/types": "^7.24.8", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/@babel/types": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz", + "integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==", + "dependencies": { + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@base2/pretty-print-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz", + "integrity": "sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA==", + "dev": true + }, + "node_modules/@chromatic-com/storybook": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@chromatic-com/storybook/-/storybook-1.6.1.tgz", + "integrity": "sha512-x1x1NB3j4xpfeSWKr96emc+7ZvfsvH+/WVb3XCjkB24PPbT8VZXb3mJSAQMrSzuQ8+eQE9kDogYHH9Fj3tb/Cw==", + "dev": true, + "dependencies": { + "chromatic": "^11.4.0", + "filesize": "^10.0.12", + "jsonfile": "^6.1.0", + "react-confetti": "^6.1.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=16.0.0", + "yarn": ">=1.22.18" + } + }, + "node_modules/@chromatic-com/storybook/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@chromatic-com/storybook/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", + "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", + "dependencies": { + "@emotion/memoize": "^0.8.1", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/react": { + "version": "11.11.4", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", + "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz", + "integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==", + "dependencies": { + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", + "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" + }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", + "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/compat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.0.tgz", + "integrity": "sha512-s9Wi/p25+KbzxKlDm3VshQdImhWk+cbdblhwGNnyCU5lpSwtWa4v7VQCxSki0FAUrGA3s8nCWgYzAH41mwQVKQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", + "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-array/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@eslint/eslintrc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@eslint/js": { + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", + "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mdx-js/react": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", + "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", + "dev": true, + "dependencies": { + "@types/mdx": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@remix-run/router": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.17.1.tgz", + "integrity": "sha512-mCOMec4BKd6BRGBZeSnGiIgwsbLGp3yhVqAD8H+PxiRNEHgDpZb8J1TnrSDlg97t0ySKMQJTHCWBCmBpSmkF6Q==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/addon-actions": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.2.2.tgz", + "integrity": "sha512-SN4cSRt3f0qXi5te+yhMseSdQuZntA8lGlASbRmN77YQTpIaGsNiH88xFoky0s9qz531hiRfU1R0ZSMylBwSKw==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "@types/uuid": "^9.0.1", + "dequal": "^2.0.2", + "polished": "^4.2.2", + "uuid": "^9.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-actions/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@storybook/addon-backgrounds": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-8.2.2.tgz", + "integrity": "sha512-m/xJe7uKL+kfJx7pQcHwAeIvJ3tdLIpDGrMAVDNDJHcAxfe44cFjIInaV/1HKf3y5Awap+DZFW66ekkxuI9zzA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "memoizerific": "^1.11.3", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-controls": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-8.2.2.tgz", + "integrity": "sha512-y241aOANGzT5XBADUIvALwG/xF5eC6UItzmWJaFvOzSBCq74GIA0+Hu9atyFdvFQbXOrdvPWC4jR+9iuBFRxAA==", + "dev": true, + "dependencies": { + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-docs": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.2.2.tgz", + "integrity": "sha512-qk/yjAR9RpsSrKLLbeCgb6u58c8TmYqyJSnXgbAozZZNKHBWlIpvZ/hTNYud8qo0coPlxnLdjnZf32TykWGlAg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.24.4", + "@mdx-js/react": "^3.0.0", + "@storybook/blocks": "8.2.2", + "@storybook/csf-plugin": "8.2.2", + "@storybook/global": "^5.0.0", + "@storybook/react-dom-shim": "8.2.2", + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "fs-extra": "^11.1.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "rehype-external-links": "^3.0.0", + "rehype-slug": "^6.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-docs/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@storybook/addon-essentials": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.2.2.tgz", + "integrity": "sha512-yN//BFMbSvNV0+Sll2hcKmgJX06TUKQDm6pZimUjkXczFtOmK7K/UdDmKjWS+qjhfJdWpxdRoEpxoHvvRmNfsA==", + "dev": true, + "dependencies": { + "@storybook/addon-actions": "8.2.2", + "@storybook/addon-backgrounds": "8.2.2", + "@storybook/addon-controls": "8.2.2", + "@storybook/addon-docs": "8.2.2", + "@storybook/addon-highlight": "8.2.2", + "@storybook/addon-measure": "8.2.2", + "@storybook/addon-outline": "8.2.2", + "@storybook/addon-toolbars": "8.2.2", + "@storybook/addon-viewport": "8.2.2", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-highlight": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-8.2.2.tgz", + "integrity": "sha512-yDTRzzL+IJAymgY32xoZl09BGBVmPOUV2wVNGYcZkkBLvz2GSQMTfUe1/7F4jAx//+rFBu48/MQzsTC7Bk8kPw==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-interactions": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-8.2.2.tgz", + "integrity": "sha512-zRRuUwm/l41JtTUgjIoQTUgLT99Hsdz9cqKca/8NYo1MGBdEcKE41DH4aBIzKaOKFu7p9q00/o/X1EqYX4LMUA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "@storybook/instrumenter": "8.2.2", + "@storybook/test": "8.2.2", + "polished": "^4.2.2", + "ts-dedent": "^2.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-links": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-8.2.2.tgz", + "integrity": "sha512-eGh7O7SgTJMtnuXC0HlRPOegu1njcJS2cnVqjbzjvjxsPSBhbHpdYMi9Q9E7al/FKuqMUOjIR9YLIlmK1AJaqA==", + "dev": true, + "dependencies": { + "@storybook/csf": "0.1.11", + "@storybook/global": "^5.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.2" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } + }, + "node_modules/@storybook/addon-measure": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-8.2.2.tgz", + "integrity": "sha512-3rCo/aMltt5FrBVdr2dYlD8HlE2q9TLKGJZnwh9on4QyL6ArHbdYw0LmyHe/LrFahJ49w1XQZBMSJcAdRkkS7w==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-onboarding": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-onboarding/-/addon-onboarding-8.2.2.tgz", + "integrity": "sha512-dCdE8Mt/JW6cq6dY7co35Sul/bAkUT3ixaxBrUagFUYUQ/PTYM6p4/B+45RURD5S9z8LVHH1rVgmEeScm3U78w==", + "dev": true, + "dependencies": { + "react-confetti": "^6.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-outline": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-8.2.2.tgz", + "integrity": "sha512-Y+PQtfTNO8GLX5nz+3x5AMfHNvdGvBXazJ29+Rl1ygYN1+Q9ZhRJDE1kAK0wLxb7CG14peAgdYEaQb3Rduv7HQ==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-toolbars": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-8.2.2.tgz", + "integrity": "sha512-JGOueOc3EPljlCl9dVSQee0aMYoqGNvN0UH+R6wYJ3bDZ+tUG/iYpsZVPUOvS8vzp3Imk5Is1kzQbQYJtzdGLg==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-viewport": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-8.2.2.tgz", + "integrity": "sha512-gkZ8bsjGGP0NuevkT2iKC+szezSy+w4BrBDknf490mRU2K/B2e7TGojf/j/AtxzILMzD4IKzKUXbE/zwcqjZvA==", + "dev": true, + "dependencies": { + "memoizerific": "^1.11.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-webpack5-compiler-swc": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-swc/-/addon-webpack5-compiler-swc-1.0.5.tgz", + "integrity": "sha512-1NlM3noit2vA22OyWb8Ma2lhcEKCS1Snv2kr+EkaVABUqNDfVc9AD/GgYQhF7F/2CoF5N2JU7uzXDzFHd5TzZg==", + "dependencies": { + "@swc/core": "^1.7.3", + "swc-loader": "^0.2.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@storybook/blocks": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.2.2.tgz", + "integrity": "sha512-av0Tryg4toDl2L/d1ABErtsAk9wvM1su6+M4wq5/Go50sk5IjGTldhbZFa9zNOohxLkZwaj0Q5xAgJ1Y+m5KrQ==", + "dev": true, + "dependencies": { + "@storybook/csf": "0.1.11", + "@storybook/global": "^5.0.0", + "@storybook/icons": "^1.2.5", + "@types/lodash": "^4.14.167", + "color-convert": "^2.0.1", + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "markdown-to-jsx": "^7.4.5", + "memoizerific": "^1.11.3", + "polished": "^4.2.2", + "react-colorful": "^5.1.2", + "telejson": "^7.2.0", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.2" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack5": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-8.2.3.tgz", + "integrity": "sha512-yU9rtcVpo12vD8m/nbdepyJ09K937ZnSsrvIM9XfzbxXA/+p4Cov9Rjg1VfoWyRd1ApxaztSktQlawBlb6bKEA==", + "dev": true, + "dependencies": { + "@storybook/core-webpack": "8.2.3", + "@types/node": "^18.0.0", + "@types/semver": "^7.3.4", + "browser-assert": "^1.2.1", + "case-sensitive-paths-webpack-plugin": "^2.4.0", + "cjs-module-lexer": "^1.2.3", + "constants-browserify": "^1.0.0", + "css-loader": "^6.7.1", + "es-module-lexer": "^1.5.0", + "express": "^4.19.2", + "fork-ts-checker-webpack-plugin": "^8.0.0", + "fs-extra": "^11.1.0", + "html-webpack-plugin": "^5.5.0", + "magic-string": "^0.30.5", + "path-browserify": "^1.0.1", + "process": "^0.11.10", + "semver": "^7.3.7", + "style-loader": "^3.3.1", + "terser-webpack-plugin": "^5.3.1", + "ts-dedent": "^2.0.0", + "url": "^0.11.0", + "util": "^0.12.4", + "util-deprecate": "^1.0.2", + "webpack": "5", + "webpack-dev-middleware": "^6.1.2", + "webpack-hot-middleware": "^2.25.1", + "webpack-virtual-modules": "^0.6.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.3" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-8.0.0.tgz", + "integrity": "sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cosmiconfig": "^7.0.1", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">=12.13.0", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "typescript": ">3.6.0", + "webpack": "^5.11.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/@storybook/builder-webpack5/node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.3.tgz", + "integrity": "sha512-A4ChP0Qj8oGociTs6UdlRUGANIGrCDL3y+pmQMc+dSsraXHCatFpmMey4mYELA+juqwUqwQsUgJJISXl1KWmiw==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.12", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@storybook/codemod": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-8.2.2.tgz", + "integrity": "sha512-wRUVKLHVUhbLJYKW3QOufUxJGwaUT4jTCD8+HOGpHPdJO3NrwXu186xt4tuPZO2Y/NnacPeCQPsaK5ok4O8o7A==", + "dev": true, + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/preset-env": "^7.24.4", + "@babel/types": "^7.24.0", + "@storybook/core": "8.2.2", + "@storybook/csf": "0.1.11", + "@types/cross-spawn": "^6.0.2", + "cross-spawn": "^7.0.3", + "globby": "^14.0.1", + "jscodeshift": "^0.15.1", + "lodash": "^4.17.21", + "prettier": "^3.1.1", + "recast": "^0.23.5", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/codemod/node_modules/globby": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", + "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/codemod/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/codemod/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/core": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/core/-/core-8.2.2.tgz", + "integrity": "sha512-L4ojYI+Os/i5bCReDIlFgEDQSS94mbJlNU9WRzEGZpqNC5/hbFEC9Tip7P1MiRx9NrewkzU7b+UCP7mi3e4drQ==", + "dev": true, + "dependencies": { + "@storybook/csf": "0.1.11", + "@types/express": "^4.17.21", + "@types/node": "^18.0.0", + "browser-assert": "^1.2.1", + "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0", + "esbuild-register": "^3.5.0", + "express": "^4.19.2", + "process": "^0.11.10", + "recast": "^0.23.5", + "util": "^0.12.4", + "ws": "^8.2.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/core-webpack": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.2.3.tgz", + "integrity": "sha512-0M4mJM6i4Oqp1javRMg/8wJW7VJ6p6Z8GKp6evfHLEWZAzdnexQIkPd5FFaDlFXbQNH1H0oJ+6ei4nIBtEegKg==", + "dev": true, + "dependencies": { + "@types/node": "^18.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.3" + } + }, + "node_modules/@storybook/core-webpack/node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/core/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core/node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/core/node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/@storybook/csf": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.11.tgz", + "integrity": "sha512-dHYFQH3mA+EtnCkHXzicbLgsvzYjcDJ1JWsogbItZogkPHgSJM/Wr71uMkcvw8v9mmCyP4NpXJuu6bPoVsOnzg==", + "dev": true, + "dependencies": { + "type-fest": "^2.19.0" + } + }, + "node_modules/@storybook/csf-plugin": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-8.2.2.tgz", + "integrity": "sha512-3K2RUpDDvq3DT46qAIj2VBC+fzTTebRUcZUsRfS6G1AzaX9p25iClEHiwcJacFkgQKhkci8A/Ly3Z4JJ3b4Pgw==", + "dev": true, + "dependencies": { + "unplugin": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/global": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz", + "integrity": "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==", + "dev": true + }, + "node_modules/@storybook/icons": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-1.2.9.tgz", + "integrity": "sha512-cOmylsz25SYXaJL/gvTk/dl3pyk7yBFRfeXTsHvTA3dfhoU/LWSq0NKL9nM7WBasJyn6XPSGnLS4RtKXLw5EUg==", + "dev": true, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@storybook/instrumenter": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-8.2.2.tgz", + "integrity": "sha512-refwnHqKHhya45MgqakhMG0jKhTiEIAl0aOwAaQy9+zf9ncMIYQAXRQsSZ2Z188lFWE24wbeHKteb62a5ZfWwQ==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "@vitest/utils": "^1.3.1", + "util": "^0.12.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/preset-react-webpack": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-8.2.3.tgz", + "integrity": "sha512-i886+vCMGlpFgOAOIg6BxSHgt38MXS6gqNX8Z65KVVIlI6i/9WqEQeHYfukbdGvVZ96cYWmdrnqUieIIkdCdBw==", + "dev": true, + "dependencies": { + "@storybook/core-webpack": "8.2.3", + "@storybook/react": "8.2.3", + "@storybook/react-docgen-typescript-plugin": "1.0.6--canary.9.0c3f3b7.0", + "@types/node": "^18.0.0", + "@types/semver": "^7.3.4", + "find-up": "^5.0.0", + "fs-extra": "^11.1.0", + "magic-string": "^0.30.5", + "react-docgen": "^7.0.0", + "resolve": "^1.22.8", + "semver": "^7.3.7", + "tsconfig-paths": "^4.2.0", + "webpack": "5" + }, + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.3" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/react": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@storybook/react/-/react-8.2.3.tgz", + "integrity": "sha512-818F6pJWFBiwG0r6DiUVrV+qndwbIso2gtgJoituBgIJO2eIzNmkPNSsckbaR7u+FpE4dWiIIhmDVZSnRwvDlA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "@storybook/react-dom-shim": "8.2.3", + "@types/escodegen": "^0.0.6", + "@types/estree": "^0.0.51", + "@types/node": "^18.0.0", + "acorn": "^7.4.1", + "acorn-jsx": "^5.3.1", + "acorn-walk": "^7.2.0", + "escodegen": "^2.1.0", + "html-tags": "^3.1.0", + "lodash": "^4.17.21", + "prop-types": "^15.7.2", + "react-element-to-jsx-string": "^15.0.0", + "semver": "^7.3.7", + "ts-dedent": "^2.0.0", + "type-fest": "~2.19", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.3", + "typescript": ">= 4.2.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/react-docgen-typescript-plugin": { + "version": "1.0.6--canary.9.0c3f3b7.0", + "resolved": "https://registry.npmjs.org/@storybook/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-1.0.6--canary.9.0c3f3b7.0.tgz", + "integrity": "sha512-KUqXC3oa9JuQ0kZJLBhVdS4lOneKTOopnNBK4tUAgoxWQ3u/IjzdueZjFr7gyBrXMoU6duutk3RQR9u8ZpYJ4Q==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "endent": "^2.0.1", + "find-cache-dir": "^3.3.1", + "flat-cache": "^3.0.4", + "micromatch": "^4.0.2", + "react-docgen-typescript": "^2.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "typescript": ">= 4.x", + "webpack": ">= 4" + } + }, + "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@storybook/react-dom-shim": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.2.2.tgz", + "integrity": "sha512-4fb1/yT9WXHzHjs0In6orIEZxga5eXd9UaXEFGudBgowCjDUVP9LabDdKTbGusz20lfaAkATsRG/W+EcSLoh8w==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/react-webpack5": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@storybook/react-webpack5/-/react-webpack5-8.2.3.tgz", + "integrity": "sha512-lcm73r8S5Uy2ENuFDSR07fW+KRSYGNcrF53VItP+rgFZHrOm7gaeebrjSIA6r4tQwdd9218VaqpQGFrKAURS2w==", + "dev": true, + "dependencies": { + "@storybook/builder-webpack5": "8.2.3", + "@storybook/preset-react-webpack": "8.2.3", + "@storybook/react": "8.2.3", + "@types/node": "^18.0.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.3", + "typescript": ">= 4.2.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/react-webpack5/node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/react/node_modules/@storybook/react-dom-shim": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.2.3.tgz", + "integrity": "sha512-N8AsM6N1S867GGWt2J2q5oY5ryqxohh3y1HqNtjg+wXf5+RkTD6M2Cgqe6p+JHz81nDKyvvVzP60MvvDhY5VOA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.3" + } + }, + "node_modules/@storybook/react/node_modules/@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true + }, + "node_modules/@storybook/react/node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/react/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/@storybook/test": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/test/-/test-8.2.2.tgz", + "integrity": "sha512-X2qAKErjTh1X7XLAZqCMtU0ZK8JuwdKmgiqU0oXWxIDmCX6/Dm9ZIcdMZHs/S+K/UnIByjNlQpTShLVfRUeN1w==", + "dev": true, + "dependencies": { + "@storybook/csf": "0.1.11", + "@storybook/instrumenter": "8.2.2", + "@testing-library/dom": "10.1.0", + "@testing-library/jest-dom": "6.4.5", + "@testing-library/user-event": "14.5.2", + "@vitest/expect": "1.6.0", + "@vitest/spy": "1.6.0", + "util": "^0.12.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", + "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", + "dependencies": { + "cosmiconfig": "^8.1.3", + "deepmerge": "^4.3.1", + "svgo": "^3.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", + "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", + "dependencies": { + "@babel/core": "^7.21.3", + "@babel/plugin-transform-react-constant-elements": "^7.21.3", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@svgr/core": "8.1.0", + "@svgr/plugin-jsx": "8.1.0", + "@svgr/plugin-svgo": "8.1.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@swc/core": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.6.tgz", + "integrity": "sha512-FZxyao9eQks1MRmUshgsZTmlg/HB2oXK5fghkoWJm/1CU2q2kaJlVDll2as5j+rmWiwkp0Gidlq8wlXcEEAO+g==", + "hasInstallScript": true, + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.12" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.7.6", + "@swc/core-darwin-x64": "1.7.6", + "@swc/core-linux-arm-gnueabihf": "1.7.6", + "@swc/core-linux-arm64-gnu": "1.7.6", + "@swc/core-linux-arm64-musl": "1.7.6", + "@swc/core-linux-x64-gnu": "1.7.6", + "@swc/core-linux-x64-musl": "1.7.6", + "@swc/core-win32-arm64-msvc": "1.7.6", + "@swc/core-win32-ia32-msvc": "1.7.6", + "@swc/core-win32-x64-msvc": "1.7.6" + }, + "peerDependencies": { + "@swc/helpers": "*" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.6.tgz", + "integrity": "sha512-6lYHey84ZzsdtC7UuPheM4Rm0Inzxm6Sb8U6dmKc4eCx8JL0LfWG4LC5RsdsrTxnjTsbriWlnhZBffh8ijUHIQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" + }, + "node_modules/@swc/types": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", + "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, + "node_modules/@testing-library/dom": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.1.0.tgz", + "integrity": "sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/dom/node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.5.tgz", + "integrity": "sha512-AguB9yvTXmCnySBP1lWjfNNUwpbElsaQ567lt2VdGqAdHtpieLgjmcVyv1q7PMIvLbgpDdkWV5Ydv3FEejyp2A==", + "dev": true, + "dependencies": { + "@adobe/css-tools": "^4.3.2", + "@babel/runtime": "^7.9.2", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", + "redent": "^3.0.0" + }, + "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 + } + } + }, + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true + }, + "node_modules/@testing-library/jest-dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/user-event": { + "version": "14.5.2", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz", + "integrity": "sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==", + "dev": true, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/doctrine": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.9.tgz", + "integrity": "sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==", + "dev": true + }, + "node_modules/@types/emscripten": { + "version": "1.39.13", + "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.13.tgz", + "integrity": "sha512-cFq+fO/isvhvmuP/+Sl4K4jtU6E23DoivtbO4r50e3odaxAiVdbfSYRDdJ4gCdxx+3aRjhphS5ZMwIH4hFy/Cw==", + "dev": true + }, + "node_modules/@types/escodegen": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/escodegen/-/escodegen-0.0.6.tgz", + "integrity": "sha512-AjwI4MvWx3HAOaZqYsjKWyEObT9lcVV0Y0V8nXo6cXzN8ZiMxVhf6F3d/UNvXVGKrEzL/Dluc5p+y9GkzlTWig==", + "dev": true + }, + "node_modules/@types/eslint": { + "version": "8.56.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", + "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.5", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", + "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/lodash": { + "version": "4.17.6", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.6.tgz", + "integrity": "sha512-OpXEVoCKSS3lQqjx9GGGOapBeuW5eUboYHRlHP9urXPX25IKZ6AnP5ZRxtVf63iieUbsHxLn8NQ5Nlftc6yzAA==", + "dev": true + }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.14.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", + "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "dev": true + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/react": { + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/resolve": { + "version": "1.20.6", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz", + "integrity": "sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", + "dev": true + }, + "node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", + "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/type-utils": "7.16.0", + "@typescript-eslint/utils": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", + "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.16.0", + "@typescript-eslint/utils": "7.16.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", + "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.0.tgz", + "integrity": "sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", + "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", + "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", + "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", + "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.16.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@vitest/expect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz", + "integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==", + "dev": true, + "dependencies": { + "@vitest/spy": "1.6.0", + "@vitest/utils": "1.6.0", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz", + "integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==", + "dev": true, + "dependencies": { + "tinyspy": "^2.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz", + "integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==", + "dev": true, + "dependencies": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@vitest/utils/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@vitest/utils/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/@yarnpkg/fslib": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@yarnpkg/fslib/-/fslib-2.10.3.tgz", + "integrity": "sha512-41H+Ga78xT9sHvWLlFOZLIhtU6mTGZ20pZ29EiZa97vnxdohJD2AF42rCoAoWfqUz486xY6fhjMH+DYEM9r14A==", + "dev": true, + "dependencies": { + "@yarnpkg/libzip": "^2.3.0", + "tslib": "^1.13.0" + }, + "engines": { + "node": ">=12 <14 || 14.2 - 14.9 || >14.10.0" + } + }, + "node_modules/@yarnpkg/fslib/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@yarnpkg/libzip": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/libzip/-/libzip-2.3.0.tgz", + "integrity": "sha512-6xm38yGVIa6mKm/DUCF2zFFJhERh/QWp1ufm4cNUvxsONBmfPg8uZ9pZBdOmF6qFGr/HlT6ABBkCSx/dlEtvWg==", + "dev": true, + "dependencies": { + "@types/emscripten": "^1.39.6", + "tslib": "^1.13.0" + }, + "engines": { + "node": ">=12 <14 || 14.2 - 14.9 || >14.10.0" + } + }, + "node_modules/@yarnpkg/libzip/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", + "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.toreversed": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", + "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.9.1.tgz", + "integrity": "sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/babel-core": { + "version": "7.0.0-bridge.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", + "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", + "dev": true, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/babel-plugin-macros/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", + "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.1", + "core-js-compat": "^3.36.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-assert": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz", + "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==", + "dev": true + }, + "node_modules/browserslist": { + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", + "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001640", + "electron-to-chromium": "^1.4.820", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "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" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001642", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz", + "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/case-sensitive-paths-webpack-plugin": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", + "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/chai": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", + "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "dev": true, + "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.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chromatic": { + "version": "11.5.5", + "resolved": "https://registry.npmjs.org/chromatic/-/chromatic-11.5.5.tgz", + "integrity": "sha512-YS0GJwegF0vpMbwZE68/xJlI4SlUGMqI78V2ATAF19YwTHaq8jGP1CPQGKUSlgWUhzPtyu3ELy6Dvv/owYljAg==", + "dev": true, + "bin": { + "chroma": "dist/bin.js", + "chromatic": "dist/bin.js", + "chromatic-cli": "dist/bin.js" + }, + "peerDependencies": { + "@chromatic-com/cypress": "^0.*.* || ^1.0.0", + "@chromatic-com/playwright": "^0.*.* || ^1.0.0" + }, + "peerDependenciesMeta": { + "@chromatic-com/cypress": { + "optional": true + }, + "@chromatic-com/playwright": { + "optional": true + } + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "dev": true, + "dependencies": { + "consola": "^3.2.3" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", + "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", + "dev": true + }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, + "node_modules/compare-versions": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz", + "integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/confbox": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", + "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", + "dev": true + }, + "node_modules/consola": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", + "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", + "dev": true, + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, + "node_modules/core-js-compat": { + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", + "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", + "dependencies": { + "browserslist": "^4.23.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "dev": true, + "dependencies": { + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/crypto-random-string/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true + }, + "node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-equal/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "dev": true + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.827", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.827.tgz", + "integrity": "sha512-VY+J0e4SFcNfQy19MEoMdaIcZLmDCprqvBtkii1WTCTQHpRvf5N8+3kTYCgL/PcntvwQvmMJWTuDPsq+IlhWKQ==" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/endent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/endent/-/endent-2.1.0.tgz", + "integrity": "sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w==", + "dev": true, + "dependencies": { + "dedent": "^0.7.0", + "fast-json-parse": "^1.0.3", + "objectorarray": "^1.0.5" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.17.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", + "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/envinfo": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", + "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-get-iterator/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/es-iterator-helpers": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", + "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", + "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.23.0", + "@esbuild/android-arm": "0.23.0", + "@esbuild/android-arm64": "0.23.0", + "@esbuild/android-x64": "0.23.0", + "@esbuild/darwin-arm64": "0.23.0", + "@esbuild/darwin-x64": "0.23.0", + "@esbuild/freebsd-arm64": "0.23.0", + "@esbuild/freebsd-x64": "0.23.0", + "@esbuild/linux-arm": "0.23.0", + "@esbuild/linux-arm64": "0.23.0", + "@esbuild/linux-ia32": "0.23.0", + "@esbuild/linux-loong64": "0.23.0", + "@esbuild/linux-mips64el": "0.23.0", + "@esbuild/linux-ppc64": "0.23.0", + "@esbuild/linux-riscv64": "0.23.0", + "@esbuild/linux-s390x": "0.23.0", + "@esbuild/linux-x64": "0.23.0", + "@esbuild/netbsd-x64": "0.23.0", + "@esbuild/openbsd-arm64": "0.23.0", + "@esbuild/openbsd-x64": "0.23.0", + "@esbuild/sunos-x64": "0.23.0", + "@esbuild/win32-arm64": "0.23.0", + "@esbuild/win32-ia32": "0.23.0", + "@esbuild/win32-x64": "0.23.0" + } + }, + "node_modules/esbuild-register": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.5.0.tgz", + "integrity": "sha512-+4G/XmakeBAsvJuDugJvtyF1x+XJT4FMocynNpxrvEBViirpfUn2PgNpCHedfWhF4WokNsO/OvMKrmJOIJsI5A==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "peerDependencies": { + "esbuild": ">=0.12 <1" + } + }, + "node_modules/esbuild-register/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/esbuild-register/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint": { + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.8.0.tgz", + "integrity": "sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.17.1", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.8.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.0.2", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "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" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", + "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*" + } + }, + "node_modules/eslint-import-resolver-typescript/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-typescript/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/eslint-module-utils": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-import/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-import/node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz", + "integrity": "sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==", + "dev": true, + "dependencies": { + "aria-query": "~5.1.3", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.9.1", + "axobject-query": "~3.1.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "es-iterator-helpers": "^1.0.19", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.0" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", + "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.6" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.34.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.4.tgz", + "integrity": "sha512-Np+jo9bUwJNxCsT12pXtrGhJgT3T44T1sHhn1Ssr42XFn8TES0267wPGo5nNrMHi8qkyimDAX2BUmkf9pSaVzA==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.toreversed": "^1.1.2", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.19", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-storybook": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.8.0.tgz", + "integrity": "sha512-CZeVO5EzmPY7qghO2t64oaFM+8FTaD4uzOEjHKp516exyTKo+skKAL9GI3QALS2BXhyALJjNtwbmr1XinGE8bA==", + "dev": true, + "dependencies": { + "@storybook/csf": "^0.0.1", + "@typescript-eslint/utils": "^5.62.0", + "requireindex": "^1.2.0", + "ts-dedent": "^2.2.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "eslint": ">=6" + } + }, + "node_modules/eslint-plugin-storybook/node_modules/@storybook/csf": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.0.1.tgz", + "integrity": "sha512-USTLkZze5gkel8MYCujSRBVIrUQ3YPBrLOx7GNk/0wttvVtlzWXAq9eLbQ4p/NicGxP+3T7KPEMVV//g+yubpw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", + "dev": true, + "dependencies": { + "acorn": "^8.12.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dev": true, + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-parse": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz", + "integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fast-uri": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", + "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fd-package-json": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fd-package-json/-/fd-package-json-1.2.0.tgz", + "integrity": "sha512-45LSPmWf+gC5tdCQMNH4s9Sr00bIkiD9aN7dc5hqkrEw1geRYyDQS1v1oMHAW3ysfxfndqGsrDREHHjNNbKUfA==", + "dev": true, + "dependencies": { + "walk-up-path": "^3.0.1" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/file-entry-cache/node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/filesize": { + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.1.4.tgz", + "integrity": "sha512-ryBwPIIeErmxgPnm6cbESAzXjuEFubs+yKYLBZvg3CaiNcmkJChoOGcBSrZ6IwkMwPABwPpVXE6IlNdGJJrvEg==", + "dev": true, + "engines": { + "node": ">= 10.4.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flat-cache/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/flat-cache/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flat-cache/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/flow-parser": { + "version": "0.239.1", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.239.1.tgz", + "integrity": "sha512-topOrETNxJ6T2gAnQiWqAlzGPj8uI2wtmNOlDIMNB+qyvGJZ6R++STbUOTAYmvPhOMz2gXnXPH0hOvURYmrBow==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/fs-monkey": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", + "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/giget": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/giget/-/giget-1.2.3.tgz", + "integrity": "sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==", + "dev": true, + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.2.3", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.3", + "nypm": "^0.3.8", + "ohash": "^1.1.3", + "pathe": "^1.1.2", + "tar": "^6.2.0" + }, + "bin": { + "giget": "dist/cli.mjs" + } + }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", + "dev": true + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/globals": { + "version": "15.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.8.0.tgz", + "integrity": "sha512-VZAJ4cewHTExBWDHR6yptdIBlx9YSSZuwojj9Nt5mBRXQzrKakDsVKQ1J63sklLvzAJm0X5+RpO4i3Y2hcOnFw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hast-util-heading-rank": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-heading-rank/-/hast-util-heading-rank-3.0.0.tgz", + "integrity": "sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.0.tgz", + "integrity": "sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", + "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", + "dev": true, + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-absolute-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-4.0.1.tgz", + "integrity": "sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", + "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jscodeshift": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.2.tgz", + "integrity": "sha512-FquR7Okgmc4Sd0aEDwqho3rEiKR3BdvuG9jfdHjLJ6JQoWSMpavug3AoIfnfWhxFlf+5pzQh8qjqz0DWFrNQzA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.23.0", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", + "@babel/plugin-transform-optional-chaining": "^7.23.0", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/preset-flow": "^7.22.15", + "@babel/preset-typescript": "^7.23.0", + "@babel/register": "^7.22.15", + "babel-core": "^7.0.0-bridge.0", + "chalk": "^4.1.2", + "flow-parser": "0.*", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "neo-async": "^2.5.0", + "node-dir": "^0.1.17", + "recast": "^0.23.3", + "temp": "^0.8.4", + "write-file-atomic": "^2.3.0" + }, + "bin": { + "jscodeshift": "bin/jscodeshift.js" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + }, + "peerDependenciesMeta": { + "@babel/preset-env": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lottie-react": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/lottie-react/-/lottie-react-2.4.0.tgz", + "integrity": "sha512-pDJGj+AQlnlyHvOHFK7vLdsDcvbuqvwPZdMlJ360wrzGFurXeKPr8SiRCjLf3LrNYKANQtSsh5dz9UYQHuqx4w==", + "dependencies": { + "lottie-web": "^5.10.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/lottie-web": { + "version": "5.12.2", + "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz", + "integrity": "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==" + }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/map-or-similar": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", + "integrity": "sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==", + "dev": true + }, + "node_modules/markdown-to-jsx": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.4.7.tgz", + "integrity": "sha512-0+ls1IQZdU6cwM1yu0ZjjiVWYtkbExSyUIFU2ZeDIFuZM1W42Mh4OlJ4nb4apX4H8smxDHRdFaoIVJGwfv5hkg==", + "dev": true, + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "react": ">= 0.14.0" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memoizerific": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", + "integrity": "sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==", + "dev": true, + "dependencies": { + "map-or-similar": "^1.5.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mlly": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.1.tgz", + "integrity": "sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==", + "dev": true, + "dependencies": { + "acorn": "^8.11.3", + "pathe": "^1.1.2", + "pkg-types": "^1.1.1", + "ufo": "^1.5.3" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/mylas": { + "version": "2.1.13", + "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.13.tgz", + "integrity": "sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==", + "dev": true, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/raouldeheer" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "dev": true + }, + "node_modules/node-dir": { + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", + "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", + "dev": true, + "dependencies": { + "minimatch": "^3.0.2" + }, + "engines": { + "node": ">= 0.10.5" + } + }, + "node_modules/node-dir/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/node-dir/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.4.tgz", + "integrity": "sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nypm": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.9.tgz", + "integrity": "sha512-BI2SdqqTHg2d4wJh8P9A1W+bslg33vOE9IZDY6eR2QC+Pu1iNBVZUqczrd43rJb+fMzHU7ltAYKsEFY/kHMFcw==", + "dev": true, + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.2.3", + "execa": "^8.0.1", + "pathe": "^1.1.2", + "pkg-types": "^1.1.1", + "ufo": "^1.5.3" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": "^14.16.0 || >=16.10.0" + } + }, + "node_modules/nypm/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "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.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/nypm/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/nypm/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/nypm/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/objectorarray": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/objectorarray/-/objectorarray-1.0.5.tgz", + "integrity": "sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg==", + "dev": true + }, + "node_modules/ohash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.3.tgz", + "integrity": "sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==", + "dev": true + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-types": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.1.3.tgz", + "integrity": "sha512-+JrgthZG6m3ckicaOB74TwQ+tBWsFl3qVQg7mN8ulwSOElJ7gBhKzj2VkCPnZ4NlF6kEquYU+RIYNVAvzd54UA==", + "dev": true, + "dependencies": { + "confbox": "^0.1.7", + "mlly": "^1.7.1", + "pathe": "^1.1.2" + } + }, + "node_modules/plimit-lit": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", + "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", + "dev": true, + "dependencies": { + "queue-lit": "^1.5.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/polished": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz", + "integrity": "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.17.8" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.4.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", + "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz", + "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-lit": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", + "integrity": "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-colorful": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", + "integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==", + "dev": true, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/react-confetti": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-confetti/-/react-confetti-6.1.0.tgz", + "integrity": "sha512-7Ypx4vz0+g8ECVxr88W9zhcQpbeujJAVqL14ZnXJ3I23mOI9/oBVTQ3dkJhUmB0D6XOtCZEM6N0Gm9PMngkORw==", + "dev": true, + "dependencies": { + "tween-functions": "^1.2.0" + }, + "engines": { + "node": ">=10.18" + }, + "peerDependencies": { + "react": "^16.3.0 || ^17.0.1 || ^18.0.0" + } + }, + "node_modules/react-docgen": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/react-docgen/-/react-docgen-7.0.3.tgz", + "integrity": "sha512-i8aF1nyKInZnANZ4uZrH49qn1paRgBZ7wZiCNBMnenlPzEv0mRl+ShpTVEI6wZNl8sSc79xZkivtgLKQArcanQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.18.9", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9", + "@types/babel__core": "^7.18.0", + "@types/babel__traverse": "^7.18.0", + "@types/doctrine": "^0.0.9", + "@types/resolve": "^1.20.2", + "doctrine": "^3.0.0", + "resolve": "^1.22.1", + "strip-indent": "^4.0.0" + }, + "engines": { + "node": ">=16.14.0" + } + }, + "node_modules/react-docgen-typescript": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz", + "integrity": "sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==", + "dev": true, + "peerDependencies": { + "typescript": ">= 4.3.x" + } + }, + "node_modules/react-docgen/node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-element-to-jsx-string": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/react-element-to-jsx-string/-/react-element-to-jsx-string-15.0.0.tgz", + "integrity": "sha512-UDg4lXB6BzlobN60P8fHWVPX3Kyw8ORrTeBtClmIlGdkOOE+GYQSFvmEU5iLLpwp/6v42DINwNcwOhOLfQ//FQ==", + "dev": true, + "dependencies": { + "@base2/pretty-print-object": "1.0.1", + "is-plain-object": "5.0.0", + "react-is": "18.1.0" + }, + "peerDependencies": { + "react": "^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0", + "react-dom": "^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0" + } + }, + "node_modules/react-element-to-jsx-string/node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-element-to-jsx-string/node_modules/react-is": { + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", + "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "dev": true + }, + "node_modules/react-inspector": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-6.0.2.tgz", + "integrity": "sha512-x+b7LxhmHXjHoU/VrFAzw5iutsILRoYyDq97EDYdFpPLcvqtEzk4ZSZSQjnFPbr5T57tLXnHcqFYoN1pI6u8uQ==", + "dev": true, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-router": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.24.1.tgz", + "integrity": "sha512-PTXFXGK2pyXpHzVo3rR9H7ip4lSPZZc0bHG5CARmj65fTT6qG7sTngmb6lcYu1gf3y/8KxORoy9yn59pGpCnpg==", + "dependencies": { + "@remix-run/router": "1.17.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.24.1.tgz", + "integrity": "sha512-U19KtXqooqw967Vw0Qcn5cOvrX5Ejo9ORmOtJMzYWtCT4/WOfFLIZGGsVLxcd9UkBO0mSTZtXqhZBsWlHr7+Sg==", + "dependencies": { + "@remix-run/router": "1.17.1", + "react-router": "6.24.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/recast": { + "version": "0.23.9", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.9.tgz", + "integrity": "sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==", + "dev": true, + "dependencies": { + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/redent/node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/rehype-external-links": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rehype-external-links/-/rehype-external-links-3.0.0.tgz", + "integrity": "sha512-yp+e5N9V3C6bwBeAC4n796kc86M4gJCdlVhiMTxIrJG5UHDMh+PJANf9heqORJbt1nrCbDwIlAZKjANIaVBbvw==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-is-element": "^3.0.0", + "is-absolute-url": "^4.0.0", + "space-separated-tokens": "^2.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-slug": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/rehype-slug/-/rehype-slug-6.0.0.tgz", + "integrity": "sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "github-slugger": "^2.0.0", + "hast-util-heading-rank": "^3.0.0", + "hast-util-to-string": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dev": true, + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "dev": true, + "engines": { + "node": ">=0.10.5" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "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" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/storybook": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-8.2.2.tgz", + "integrity": "sha512-xDT9gyzAEFQNeK7P+Mj/8bNzN+fbm6/4D6ihdSzmczayjydpNjMs74HDHMY6S4Bfu6tRVyEK2ALPGnr6ZVofBA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/types": "^7.24.0", + "@storybook/codemod": "8.2.2", + "@storybook/core": "8.2.2", + "@types/semver": "^7.3.4", + "@yarnpkg/fslib": "2.10.3", + "@yarnpkg/libzip": "2.3.0", + "chalk": "^4.1.0", + "commander": "^6.2.1", + "cross-spawn": "^7.0.3", + "detect-indent": "^6.1.0", + "envinfo": "^7.7.3", + "execa": "^5.0.0", + "fd-package-json": "^1.2.0", + "find-up": "^5.0.0", + "fs-extra": "^11.1.0", + "giget": "^1.0.0", + "globby": "^14.0.1", + "jscodeshift": "^0.15.1", + "leven": "^3.1.0", + "ora": "^5.4.1", + "prettier": "^3.1.1", + "prompts": "^2.4.0", + "semver": "^7.3.7", + "strip-json-comments": "^3.0.1", + "tempy": "^3.1.0", + "tiny-invariant": "^1.3.1", + "ts-dedent": "^2.0.0" + }, + "bin": { + "getstorybook": "bin/index.cjs", + "sb": "bin/index.cjs", + "storybook": "bin/index.cjs" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/storybook-addon-react-router-v6": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/storybook-addon-react-router-v6/-/storybook-addon-react-router-v6-2.0.15.tgz", + "integrity": "sha512-4vOYIQwehlQLyXaCT9K0Iu0po2Z+pANGsqkfm/BQuAEjE9MoN7vrsrQLHINhKbmQVtNMmuS/oBR3GGNbqQ1gew==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "compare-versions": "^6.0.0", + "react-inspector": "6.0.2" + }, + "peerDependencies": { + "@storybook/blocks": "^7.0.0", + "@storybook/channels": "^7.0.0", + "@storybook/components": "^7.0.0", + "@storybook/core-events": "^7.0.0", + "@storybook/manager-api": "^7.0.0", + "@storybook/preview-api": "^7.0.0", + "@storybook/theming": "^7.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-router-dom": "^6.4.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/storybook/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/storybook/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/storybook/node_modules/globby": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", + "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz", + "integrity": "sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", + "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-loader": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", + "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + }, + "node_modules/svgo": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", + "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/svgo/node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/svgo/node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/svgo/node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/svgo/node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/svgo/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/swc-loader": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/swc-loader/-/swc-loader-0.2.6.tgz", + "integrity": "sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg==", + "dependencies": { + "@swc/counter": "^0.1.3" + }, + "peerDependencies": { + "@swc/core": "^1.2.147", + "webpack": ">=2" + } + }, + "node_modules/synckit": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/telejson": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/telejson/-/telejson-7.2.0.tgz", + "integrity": "sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==", + "dev": true, + "dependencies": { + "memoizerific": "^1.11.3" + } + }, + "node_modules/temp": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", + "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", + "dev": true, + "dependencies": { + "rimraf": "~2.6.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/temp-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", + "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", + "dev": true, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/temp/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/temp/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/temp/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/temp/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/tempy": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.1.0.tgz", + "integrity": "sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==", + "dev": true, + "dependencies": { + "is-stream": "^3.0.0", + "temp-dir": "^3.0.0", + "type-fest": "^2.12.2", + "unique-string": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.31.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.2.tgz", + "integrity": "sha512-LGyRZVFm/QElZHy/CPr/O4eNZOZIzsrQ92y4v9UJe/pFJjypje2yI3C2FmPtvUEnhadlSbmG2nXtdcjHOjCfxw==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true + }, + "node_modules/tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "dev": true, + "engines": { + "node": ">=6.10" + } + }, + "node_modules/ts-loader": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", + "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/ts-loader/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tsc-alias": { + "version": "1.8.10", + "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.10.tgz", + "integrity": "sha512-Ibv4KAWfFkFdKJxnWfVtdOmB0Zi1RJVxcbPGiCDsFpCQSsmpWyuzHG3rQyI5YkobWwxFPEyQfu1hdo4qLG2zPw==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.3", + "commander": "^9.0.0", + "globby": "^11.0.4", + "mylas": "^2.1.9", + "normalize-path": "^3.0.0", + "plimit-lit": "^1.2.6" + }, + "bin": { + "tsc-alias": "dist/bin/index.js" + } + }, + "node_modules/tsc-alias/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tween-functions": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tween-functions/-/tween-functions-1.2.0.tgz", + "integrity": "sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", + "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.16.0.tgz", + "integrity": "sha512-kaVRivQjOzuoCXU6+hLnjo3/baxyzWVO5GrnExkFzETRYJKVHYkrJglOu2OCm8Hi9RPDWX1PTNNTpU5KRV0+RA==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "7.16.0", + "@typescript-eslint/parser": "7.16.0", + "@typescript-eslint/utils": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", + "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/ufo": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", + "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==", + "dev": true + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unique-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", + "dev": true, + "dependencies": { + "crypto-random-string": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unplugin": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.11.0.tgz", + "integrity": "sha512-3r7VWZ/webh0SGgJScpWl2/MRCZK5d3ZYFcNaeci/GQ7Teop7zf0Nl2pUuz7G21BwPd9pcUPOC5KmJ2L3WgC5g==", + "dev": true, + "dependencies": { + "acorn": "^8.11.3", + "chokidar": "^3.6.0", + "webpack-sources": "^3.2.3", + "webpack-virtual-modules": "^0.6.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", + "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", + "dev": true, + "dependencies": { + "punycode": "^1.4.1", + "qs": "^6.11.2" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + }, + "node_modules/url/node_modules/qs": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.3.tgz", + "integrity": "sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/walk-up-path": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-3.0.1.tgz", + "integrity": "sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==", + "dev": true + }, + "node_modules/watchpack": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", + "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webpack": { + "version": "5.93.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", + "integrity": "sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.7.1", + "acorn-import-attributes": "^1.9.5", + "browserslist": "^4.21.10", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-hot-middleware": { + "version": "2.26.1", + "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.26.1.tgz", + "integrity": "sha512-khZGfAeJx6I8K9zKohEWWYN6KDlVw2DHownoe+6Vtwj1LP9WFgegXnVMSkZ/dBEBtXFwrkkydsaPFlB7f8wU2A==", + "dev": true, + "dependencies": { + "ansi-html-community": "0.0.8", + "html-entities": "^2.1.0", + "strip-ansi": "^6.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "dev": true + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "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" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "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 + } + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/HDesign/package.json b/HDesign/package.json new file mode 100644 index 000000000..062987bf1 --- /dev/null +++ b/HDesign/package.json @@ -0,0 +1,72 @@ +{ + "name": "haengdong-design", + "version": "0.1.81", + "description": "", + "main": "./dist/index.js", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "files": [ + "dist" + ], + "scripts": { + "start": "webpack serve ", + "build": "rm -rf dist && mkdir dist && tsc && cp -r ./src/assets ./dist && tsc-alias", + "storybook": "storybook dev -p 6006", + "lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'", + "format": "prettier --write {src/**/*.{js,jsx,ts,tsx,json,css,scss,md}'", + "build-storybook": "storybook build" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@chromatic-com/storybook": "^1.6.1", + "@eslint/compat": "^1.1.0", + "@eslint/js": "^9.6.0", + "@storybook/addon-essentials": "^8.2.2", + "@storybook/addon-interactions": "^8.2.2", + "@storybook/addon-links": "^8.2.2", + "@storybook/addon-onboarding": "^8.2.2", + "@storybook/blocks": "^8.2.2", + "@storybook/react": "^8.2.2", + "@storybook/react-webpack5": "^8.2.3", + "@storybook/test": "^8.2.2", + "@swc/core": "^1.7.6", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "esbuild": "^0.23.0", + "eslint": "^9.8.0", + "eslint-config-prettier": "^9.1.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-jsx-a11y": "^6.9.0", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-react": "^7.34.4", + "eslint-plugin-react-hooks": "^4.6.2", + "eslint-plugin-storybook": "^0.8.0", + "file-loader": "^6.2.0", + "globals": "^15.8.0", + "prettier": "3.3.2", + "storybook": "^8.2.2", + "storybook-addon-react-router-v6": "^2.0.15", + "ts-loader": "^9.5.1", + "tsc-alias": "^1.8.10", + "typescript": "^5.5.3", + "typescript-eslint": "^7.16.0" + }, + "dependencies": { + "@emotion/react": "^11.11.4", + "@storybook/addon-webpack5-compiler-swc": "^1.0.5", + "@svgr/webpack": "^8.1.0", + "lottie-react": "^2.4.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.24.1" + }, + "engines": { + "npm": ">=10.7.0", + "node": ">=20.15.1" + } +} diff --git a/HDesign/src/assets/buljusa.svg b/HDesign/src/assets/buljusa.svg new file mode 100644 index 000000000..fe5c47534 --- /dev/null +++ b/HDesign/src/assets/buljusa.svg @@ -0,0 +1,4 @@ + + + + diff --git a/HDesign/src/assets/confirm.svg b/HDesign/src/assets/confirm.svg new file mode 100644 index 000000000..ef31a5152 --- /dev/null +++ b/HDesign/src/assets/confirm.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/HDesign/src/assets/error.svg b/HDesign/src/assets/error.svg new file mode 100644 index 000000000..479cae34a --- /dev/null +++ b/HDesign/src/assets/error.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/HDesign/src/assets/index.ts b/HDesign/src/assets/index.ts new file mode 100644 index 000000000..a9c277581 --- /dev/null +++ b/HDesign/src/assets/index.ts @@ -0,0 +1,7 @@ +export {default as InputDelete} from '@assets/inputDelete.svg'; +export {default as Buljusa} from '@assets/buljusa.svg'; +export {default as Error} from '@assets/error.svg'; +export {default as Confirm} from '@assets/confirm.svg'; +export {default as Trash} from '@assets/trash.svg'; +export {default as Search} from '@assets/search.svg'; +export {default as RightChevron} from '@assets/rightChevron.svg'; diff --git a/HDesign/src/assets/inputDelete.svg b/HDesign/src/assets/inputDelete.svg new file mode 100644 index 000000000..4356bb854 --- /dev/null +++ b/HDesign/src/assets/inputDelete.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/HDesign/src/assets/loadingAnimation.json b/HDesign/src/assets/loadingAnimation.json new file mode 100644 index 000000000..4f507a7ea --- /dev/null +++ b/HDesign/src/assets/loadingAnimation.json @@ -0,0 +1,1176 @@ +{ + "nm": "Main Scene", + "ddd": 0, + "h": 48, + "w": 128, + "meta": { + "g": "@lottiefiles/creator 1.24.1" + }, + "layers": [ + { + "ty": 0, + "nm": " Loading Dots", + "sr": 1, + "st": 0, + "op": 81, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + 962.9629629629629, + 540.7407407407408 + ] + }, + "s": { + "a": 0, + "k": [ + 27, + 27 + ] + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 64.25999999999999, + 24.2 + ] + }, + "r": { + "a": 0, + "k": 0 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100 + } + }, + "w": 1920, + "h": 1080, + "refId": "precomp_Loading Dots_139596b3-8049-4b90-9165-55e00cf10251", + "ind": 1 + } + ], + "v": "5.7.0", + "fr": 60, + "op": 81, + "ip": 0, + "assets": [ + { + "nm": "Loading Dots", + "id": "precomp_Loading Dots_139596b3-8049-4b90-9165-55e00cf10251", + "fr": 60, + "layers": [ + { + "ty": 4, + "nm": "Dot4", + "sr": 1, + "st": 0, + "op": 360, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + -284, + 92, + 0 + ], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 50, + 50, + 100 + ], + "t": 25 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 75, + 75, + 100 + ], + "t": 39 + }, + { + "s": [ + 50, + 50, + 100 + ], + "t": 55 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 1142, + 540, + 0 + ], + "t": 25 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 1142, + 500, + 0 + ], + "t": 39 + }, + { + "s": [ + 1142, + 540, + 0 + ], + "t": 55 + } + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Ellipse 1", + "ix": 1, + "cix": 2, + "np": 3, + "it": [ + { + "ty": "el", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Ellipse", + "nm": "Ellipse Path 1", + "d": 1, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "s": { + "a": 0, + "k": [ + 120, + 120 + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "c": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 25 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.7098, + 0.4588, + 1 + ], + "t": 39 + }, + { + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 55 + } + ], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [ + -284, + 92 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 1 + }, + { + "ty": 4, + "nm": "Dot3", + "sr": 1, + "st": 0, + "op": 360, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + -284, + 92, + 0 + ], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 50, + 50, + 100 + ], + "t": 17 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 75, + 75, + 100 + ], + "t": 31 + }, + { + "s": [ + 50, + 50, + 100 + ], + "t": 47 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 1022, + 540, + 0 + ], + "t": 17 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 1022, + 500, + 0 + ], + "t": 31 + }, + { + "s": [ + 1022, + 540, + 0 + ], + "t": 47 + } + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Ellipse 1", + "ix": 1, + "cix": 2, + "np": 3, + "it": [ + { + "ty": "el", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Ellipse", + "nm": "Ellipse Path 1", + "d": 1, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "s": { + "a": 0, + "k": [ + 120, + 120 + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "c": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 17 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.7098, + 0.4588, + 1 + ], + "t": 31 + }, + { + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 47 + } + ], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [ + -284, + 92 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 2 + }, + { + "ty": 4, + "nm": "Dot2", + "sr": 1, + "st": 0, + "op": 360, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + -284, + 92, + 0 + ], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 50, + 50, + 100 + ], + "t": 9 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 75, + 75, + 100 + ], + "t": 23 + }, + { + "s": [ + 50, + 50, + 100 + ], + "t": 39 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 902, + 540, + 0 + ], + "t": 9 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 902, + 500, + 0 + ], + "t": 23 + }, + { + "s": [ + 902, + 540, + 0 + ], + "t": 39 + } + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Ellipse 1", + "ix": 1, + "cix": 2, + "np": 3, + "it": [ + { + "ty": "el", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Ellipse", + "nm": "Ellipse Path 1", + "d": 1, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "s": { + "a": 0, + "k": [ + 120, + 120 + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "c": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 9 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.7098, + 0.4588, + 1 + ], + "t": 23 + }, + { + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 39 + } + ], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [ + -284, + 92 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 3 + }, + { + "ty": 4, + "nm": "Dot1", + "sr": 1, + "st": 0, + "op": 360, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + -284, + 92, + 0 + ], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 50, + 50, + 100 + ], + "t": 0 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 75, + 75, + 100 + ], + "t": 14 + }, + { + "s": [ + 50, + 50, + 100 + ], + "t": 30 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 782, + 540, + 0 + ], + "t": 0 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 782, + 500, + 0 + ], + "t": 14 + }, + { + "s": [ + 782, + 540, + 0 + ], + "t": 30 + } + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Ellipse 1", + "ix": 1, + "cix": 2, + "np": 3, + "it": [ + { + "ty": "el", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Ellipse", + "nm": "Ellipse Path 1", + "d": 1, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "s": { + "a": 0, + "k": [ + 120, + 120 + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "c": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 0 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.7098, + 0.4588, + 1 + ], + "t": 14 + }, + { + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 30 + } + ], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [ + -284, + 92 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 4 + } + ] + } + ] +} \ No newline at end of file diff --git a/HDesign/src/assets/rightChevron.svg b/HDesign/src/assets/rightChevron.svg new file mode 100644 index 000000000..5cd777f1b --- /dev/null +++ b/HDesign/src/assets/rightChevron.svg @@ -0,0 +1,3 @@ + + + diff --git a/HDesign/src/assets/search.svg b/HDesign/src/assets/search.svg new file mode 100644 index 000000000..4f33e89c3 --- /dev/null +++ b/HDesign/src/assets/search.svg @@ -0,0 +1,3 @@ + + + diff --git a/HDesign/src/assets/svg.d.ts b/HDesign/src/assets/svg.d.ts new file mode 100644 index 000000000..2db81e756 --- /dev/null +++ b/HDesign/src/assets/svg.d.ts @@ -0,0 +1,6 @@ +declare module '*.svg' { + import type React from 'react'; + + const SVG: React.FC>; + export default SVG; +} diff --git a/HDesign/src/assets/trash.svg b/HDesign/src/assets/trash.svg new file mode 100644 index 000000000..09b228b17 --- /dev/null +++ b/HDesign/src/assets/trash.svg @@ -0,0 +1,3 @@ + + + diff --git a/HDesign/src/components/BottomSheet/BottomSheet.stories.tsx b/HDesign/src/components/BottomSheet/BottomSheet.stories.tsx new file mode 100644 index 000000000..67d4cdb37 --- /dev/null +++ b/HDesign/src/components/BottomSheet/BottomSheet.stories.tsx @@ -0,0 +1,33 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import {useState} from 'react'; + +import Button from '@components/Button/Button'; +import BottomSheet from '@components/BottomSheet/BottomSheet'; + +const meta = { + title: 'Components/BottomSheet', + component: BottomSheet, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: {}, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = { + render: ({...args}) => { + const [isOpened, setIsOpened] = useState(false); + return ( + <> + + ); +}); + +export default Button; diff --git a/HDesign/src/components/Button/Button.type.ts b/HDesign/src/components/Button/Button.type.ts new file mode 100644 index 000000000..a0402b1dc --- /dev/null +++ b/HDesign/src/components/Button/Button.type.ts @@ -0,0 +1,16 @@ +import {Theme} from '@theme/theme.type'; + +export type ButtonSize = 'small' | 'medium' | 'large'; +export type ButtonVariants = 'primary' | 'secondary' | 'tertiary' | 'destructive' | 'loading'; + +export interface ButtonStyleProps { + variants?: ButtonVariants; + size?: ButtonSize; + theme?: Theme; +} + +export interface ButtonCustomProps {} + +export type ButtonOptionProps = ButtonStyleProps & ButtonCustomProps; + +export type ButtonProps = React.ComponentProps<'button'> & ButtonOptionProps; diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx b/HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx new file mode 100644 index 000000000..c7125d4d8 --- /dev/null +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx @@ -0,0 +1,51 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import DragHandleItem from '@components/DragHandleItem/DragHandleItem'; + +const meta = { + title: 'Components/DragHandleItem', + component: DragHandleItem, + tags: ['autodocs'], + parameters: {}, + argTypes: { + backgroundColor: { + description: '', + control: {type: 'select'}, + options: ['white', 'gray', 'darkGray', 'black', 'primary', 'onPrimary', 'secondary', 'onSecondary'], + }, + hasDragHandler: { + description: '๋“œ๋ž˜๊ทธํ•  ์ˆ˜ ์žˆ๋Š” ํ•ธ๋“ค๋Ÿฌ(๋ถˆ์ฃผ์‚ฌ ์ž๊ตญ)๋ฅผ ์ผœ๊ณ  ๋Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.', + control: {type: 'boolean'}, + }, + prefix: { + description: '', + control: {type: 'text'}, + }, + suffix: { + description: '', + control: {type: 'text'}, + }, + isFixed: { + description: '์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ณ ์ •๋˜์–ด ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.', + control: {type: 'boolean'}, + }, + }, + args: { + backgroundColor: 'white', + hasDragHandler: true, + prefix: '๋ฝ•์Ÿ์ด์กฑ๋ฐœ', + suffix: '398,000 ์›', + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; + +export const FixedItem: Story = { + args: { + isFixed: true, + }, +}; diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts b/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts new file mode 100644 index 000000000..b641c5fb3 --- /dev/null +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts @@ -0,0 +1,20 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +export const dragHandleItemStyle = (theme: Theme, hasDragHandle: boolean, backgroundColor: ColorKeys) => + css({ + display: 'flex', + justifyContent: 'space-between', + padding: hasDragHandle ? '0.5rem 1rem 0.5rem 0.5rem' : '0.5rem 1rem', + borderRadius: '0.75rem', + backgroundColor: theme.colors[backgroundColor], + }); + +export const dragHandlerStyle = css({ + display: 'flex', + gap: '0.25rem', + width: '100%', +}); diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.tsx b/HDesign/src/components/DragHandleItem/DragHandleItem.tsx new file mode 100644 index 000000000..9acf38084 --- /dev/null +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.tsx @@ -0,0 +1,44 @@ +/** @jsxImportSource @emotion/react */ +import Icon from '@components/Icon/Icon'; +import Flex from '@components/Flex/Flex'; +import Text from '@components/Text/Text'; +import IsFixedIcon from '@components/IsFixedIcon/IsFixedIcon'; + +import {useTheme} from '@theme/HDesignProvider'; + +import IconButton from '../IconButton/IconButton'; + +import {dragHandleItemStyle, dragHandlerStyle} from './DragHandleItem.style'; +import {DragHandleItemProps} from './DragHandleItem.type'; + +export const DragHandleItem = ({ + hasDragHandler = false, + backgroundColor = 'white', + isFixed = false, + prefix, + suffix, + ...htmlProps +}: DragHandleItemProps) => { + const {theme} = useTheme(); + + // TODO: (@toari) : ์‚ฌ๋žŒ ์ˆ˜ ๋งŽ์„ ๋•Œ UX writing ์ฒ˜๋ฆฌ + return ( +
+
+ {hasDragHandler && ( + + + + )} + + {prefix} + + {isFixed && } + {suffix} + + +
+
+ ); +}; +export default DragHandleItem; diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.type.ts b/HDesign/src/components/DragHandleItem/DragHandleItem.type.ts new file mode 100644 index 000000000..fc0a1f520 --- /dev/null +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.type.ts @@ -0,0 +1,19 @@ +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +export interface DragHandleItemStyleProps { + theme?: Theme; + backgroundColor?: ColorKeys; +} + +export interface DragHandleItemCustomProps { + hasDragHandler?: boolean; + prefix?: string; + suffix?: string; + isFixed?: boolean; +} + +export type DragHandleItemOptionProps = DragHandleItemStyleProps & DragHandleItemCustomProps; + +export type DragHandleItemProps = React.ComponentProps<'div'> & DragHandleItemOptionProps; diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx new file mode 100644 index 000000000..46c3db8a2 --- /dev/null +++ b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx @@ -0,0 +1,90 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import DragHandleItemContainer from '@components/DragHandleItemContainer/DragHandleItemContainer'; +import DragHandleItem from '@components/DragHandleItem/DragHandleItem'; + +const meta = { + title: 'Components/DragHandleItemContainer', + component: DragHandleItemContainer, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: { + topLeftText: { + description: '', + control: {type: 'text'}, + }, + topRightText: { + description: '', + control: {type: 'text'}, + }, + bottomLeftText: { + description: '', + control: {type: 'text'}, + }, + bottomRightText: { + description: '', + control: {type: 'text'}, + }, + backgroundColor: { + description: '', + control: { + type: 'select', + options: [ + 'white', + 'black', + 'primary', + 'onPrimary', + 'secondary', + 'onSecondary', + 'tertiary', + 'onTertiary', + 'gray', + 'darkGray', + 'grayContainer', + 'lightGrayContainer', + 'error', + 'errorContainer', + 'onErrorContainer', + 'warn', + 'complete', + ], + }, + }, + }, + args: { + topLeftText: '์œผ์•„๋‹ˆ์ฐจ', + topRightText: '8๋ช…', + bottomLeftText: '์ด์•ก', + bottomRightText: '214,000 ์›', + onTopLeftTextClick: () => alert('์™ผ์ชฝ ์œ„'), + onTopRightTextClick: () => alert('์˜ค๋ฅธ์ชฝ ์œ„'), + onBottomLeftTextClick: () => alert('์™ผ์ชฝ ์•„๋ž˜'), + onBottomRightTextClick: () => alert('์˜ค๋ฅธ์ชฝ ์•„๋ž˜'), + backgroundColor: 'white', + children: ( + <> + + + + ), + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts new file mode 100644 index 000000000..b5bab9422 --- /dev/null +++ b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts @@ -0,0 +1,34 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +export const containerStyle = (theme: Theme, backgroundColor: ColorKeys) => + css({ + display: 'flex', + flexDirection: 'column', + gap: '0.5rem', + padding: '0.5rem', + borderRadius: '0.75rem', + backgroundColor: theme.colors[backgroundColor], + }); + +export const topRightTextStyle = (theme: Theme) => + css({ + position: 'relative', + cursor: 'pointer', + + '&::after': { + position: 'absolute', + bottom: '0.125rem', + left: 0, + + width: '100%', + height: '0.03125rem', + + backgroundColor: theme.colors.gray, + + content: "''", + }, + }); diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx new file mode 100644 index 000000000..a95bfb5de --- /dev/null +++ b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx @@ -0,0 +1,47 @@ +/** @jsxImportSource @emotion/react */ +import {useTheme} from '@theme/HDesignProvider'; + +import Text from '../Text/Text'; +import Flex from '../Flex/Flex'; + +import {containerStyle, topRightTextStyle} from './DragHandleItemContainer.style'; +import {DragHandleItemContainerProps} from './DragHandleItemContainer.type'; + +export const DragHandleItemContainer: React.FC = ({ + topLeftText, + bottomLeftText, + topRightText, + bottomRightText, + onTopLeftTextClick, + onBottomLeftTextClick, + onTopRightTextClick, + onBottomRightTextClick, + backgroundColor = 'white', + children, + ...htmlProps +}: DragHandleItemContainerProps) => { + const {theme} = useTheme(); + + return ( +
+ + + {topLeftText} + + + {topRightText} + + + {children} + + + {bottomLeftText} + + + {bottomRightText} + + +
+ ); +}; +export default DragHandleItemContainer; diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.type.ts b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.type.ts new file mode 100644 index 000000000..1bf1129e4 --- /dev/null +++ b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.type.ts @@ -0,0 +1,20 @@ +import {ColorKeys} from '@token/colors'; + +export interface DragHandleItemContainerStyleProps { + backgroundColor?: ColorKeys; +} + +export interface DragHandleItemContainerCustomProps { + topLeftText?: string; + onTopLeftTextClick?: () => void; + bottomLeftText?: string; + onBottomLeftTextClick?: () => void; + topRightText?: string; + onTopRightTextClick?: () => void; + bottomRightText?: string; + onBottomRightTextClick?: () => void; +} + +export type DragHandleItemContainerOptionProps = DragHandleItemContainerStyleProps & DragHandleItemContainerCustomProps; + +export type DragHandleItemContainerProps = React.ComponentProps<'div'> & DragHandleItemContainerOptionProps; diff --git a/HDesign/src/components/EditableItem/EditableItem.Input.style.ts b/HDesign/src/components/EditableItem/EditableItem.Input.style.ts new file mode 100644 index 000000000..eadff482e --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.Input.style.ts @@ -0,0 +1,84 @@ +import {css} from '@emotion/react'; + +import {TextSize} from '@components/Text/Text.type'; +import {WithTheme} from '@type/withTheme'; + +import TYPOGRAPHY from '@token/typography'; + +type UnderlineProps = { + hasFocus: boolean; + hasError: boolean; +}; + +type InputSizeStyleProps = { + textSize: TextSize; +}; + +type InputStyleProps = InputSizeStyleProps; + +export const inputWrapperStyle = css({ + display: 'inline-block', +}); + +export const inputStyle = ({theme, textSize}: WithTheme) => [ + inputSizeStyle({textSize}), + inputBaseStyle({theme}), +]; + +const inputSizeStyle = ({textSize}: InputSizeStyleProps) => { + const style = { + head: css(TYPOGRAPHY.head), + title: css(TYPOGRAPHY.title), + subTitle: css(TYPOGRAPHY.subTitle), + bodyBold: css(TYPOGRAPHY.bodyBold), + body: css(TYPOGRAPHY.body), + smallBodyBold: css(TYPOGRAPHY.smallBodyBold), + smallBody: css(TYPOGRAPHY.smallBody), + captionBold: css(TYPOGRAPHY.captionBold), + caption: css(TYPOGRAPHY.caption), + tiny: css(TYPOGRAPHY.tiny), + }; + + return [style[textSize]]; +}; + +const inputBaseStyle = ({theme}: WithTheme) => + css({ + border: 'none', + outline: 'none', + paddingBottom: '0.125rem', + + color: theme.colors.black, + + '&:placeholder': { + color: theme.colors.darkGray, + }, + }); + +export const editingContainerStyle = css({ + opacity: 0, + whiteSpace: 'pre', + position: 'absolute', + pointerEvents: 'none', + padding: 0, + margin: 0, +}); + +export const underlineStyle = ({theme, hasFocus, hasError}: WithTheme) => + css({ + position: 'relative', + display: 'inline-block', + + '&::after': { + content: '""', + position: 'absolute', + + left: 0, + right: 0, + bottom: 0, + height: '0.125rem', + backgroundColor: hasFocus ? theme.colors.primary : hasError ? theme.colors.error : 'transparent', + transition: 'background-color 0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + }, + }); diff --git a/HDesign/src/components/EditableItem/EditableItem.Input.tsx b/HDesign/src/components/EditableItem/EditableItem.Input.tsx new file mode 100644 index 000000000..c0a08bc0e --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.Input.tsx @@ -0,0 +1,54 @@ +/** @jsxImportSource @emotion/react */ +import {forwardRef, useEffect, useImperativeHandle, useRef} from 'react'; + +import Flex from '@components/Flex/Flex'; +import Text from '@components/Text/Text'; +import IsFixedIcon from '@components/IsFixedIcon/IsFixedIcon'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {editingContainerStyle, inputStyle, inputWrapperStyle, underlineStyle} from './EditableItem.Input.style'; +import {InputProps} from './EditableItem.Input.type'; +import useEditableItemInput from './useEditableItemInput'; + +export const EditableItemInput = forwardRef(function Input( + {isFixed = false, textSize = 'body', hasError = false, readOnly = false, ...htmlProps}, + ref, +) { + const {theme} = useTheme(); + const inputRef = useRef(null); + const shadowRef = useRef(null); + const {hasFocus} = useEditableItemInput({inputRef}); + useImperativeHandle(ref, () => inputRef.current!); + + useEffect(() => { + if (shadowRef.current && inputRef.current) { + inputRef.current.style.width = `${shadowRef.current.offsetWidth}px`; + } + }, [htmlProps.value]); + + return ( +
+ +
+ {htmlProps.value || htmlProps.placeholder} +
+ {isFixed && } +
+ +
+
+
+ ); +}); + +export default EditableItemInput; diff --git a/HDesign/src/components/EditableItem/EditableItem.Input.type.ts b/HDesign/src/components/EditableItem/EditableItem.Input.type.ts new file mode 100644 index 000000000..8fdd3d64a --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.Input.type.ts @@ -0,0 +1,22 @@ +import {TextSize} from '@components/Text/Text.type'; + +import {Theme} from '@theme/theme.type'; + +export interface InputStyleProps { + hasError?: boolean; + textSize?: TextSize; +} + +export interface InputCustomProps { + isFixed?: boolean; + value: string | number; + readOnly?: boolean; +} + +export interface InputStylePropsWithTheme extends InputStyleProps { + theme: Theme; +} + +export type InputOptionProps = InputStyleProps & InputCustomProps; + +export type InputProps = React.ComponentProps<'input'> & InputOptionProps; diff --git a/HDesign/src/components/EditableItem/EditableItem.context.tsx b/HDesign/src/components/EditableItem/EditableItem.context.tsx new file mode 100644 index 000000000..a2aeef4bc --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.context.tsx @@ -0,0 +1,23 @@ +/** @jsxImportSource @emotion/react */ +import {createContext, PropsWithChildren, useContext, useState} from 'react'; + +interface EditableItemContextProps { + hasAnyFocus: boolean; + setHasAnyFocus: React.Dispatch>; +} + +const EditableItemContext = createContext(null); + +export const useEditableItemContext = () => { + const context = useContext(EditableItemContext); + if (!context) { + throw new Error('useEditableItemContext must be used within an EditableItemProvider'); + } + return context; +}; + +export const EditableItemProvider: React.FC = ({children}: React.PropsWithChildren) => { + const [hasAnyFocus, setHasAnyFocus] = useState(false); + + return {children}; +}; diff --git a/HDesign/src/components/EditableItem/EditableItem.input.stories.tsx b/HDesign/src/components/EditableItem/EditableItem.input.stories.tsx new file mode 100644 index 000000000..370d07c89 --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.input.stories.tsx @@ -0,0 +1,45 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import EditableItemInput from '@components/EditableItem/EditableItem.Input'; + +import EditableItem from './EditableItem'; +import {EditableItemProvider} from './EditableItem.context'; + +const meta = { + title: 'Components/EditableItemInput', + component: EditableItemInput, + tags: ['autodocs'], + parameters: {}, + argTypes: { + textSize: { + description: '', + control: {type: 'select'}, + }, + hasError: { + description: '', + control: {type: 'boolean'}, + }, + }, + args: { + placeholder: '์ง€์ถœ ๋‚ด์—ญ', + textSize: 'body', + hasError: false, + autoFocus: true, + value: '๊ฐ’', + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = { + render: ({...args}) => { + return ( + + + + ); + }, +}; diff --git a/HDesign/src/components/EditableItem/EditableItem.stories.tsx b/HDesign/src/components/EditableItem/EditableItem.stories.tsx new file mode 100644 index 000000000..38406727e --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.stories.tsx @@ -0,0 +1,276 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import {useState} from 'react'; + +import EditableItem from '@components/EditableItem/EditableItem'; +import Flex from '@components/Flex/Flex'; +import Text from '@components/Text/Text'; + +const meta = { + title: 'Components/EditableItem', + component: EditableItem, + tags: ['autodocs'], + parameters: {}, + argTypes: { + backgroundColor: { + description: '', + control: {type: 'select'}, + }, + }, + args: { + backgroundColor: 'lightGrayContainer', + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = { + render: ({...args}) => { + const [value, setValue] = useState(''); + const [value2, setValue2] = useState(''); + + return ( + console.log('focus')} + onBlur={() => console.log('blur')} + > + setValue(e.target.value)} + placeholder="์ง€์ถœ ๋‚ด์—ญ" + textSize="bodyBold" + > + + setValue2(e.target.value)} + placeholder="0" + type="number" + style={{textAlign: 'right'}} + > + ์› + + + ); + }, +}; + +export const WithLabel: Story = { + render: ({...args}) => { + const [value, setValue] = useState(''); + const [value2, setValue2] = useState(''); + + return ( + console.log('focus')} + onBlur={() => console.log('blur')} + > + setValue(e.target.value)} + placeholder="์ง€์ถœ ๋‚ด์—ญ" + textSize="bodyBold" + > + + setValue2(e.target.value)} + placeholder="0" + type="number" + style={{textAlign: 'right'}} + > + ์› + + + ); + }, +}; + +export const WithLabelAndIsFixedIcon: Story = { + render: ({...args}) => { + const [value, setValue] = useState(''); + const [value2, setValue2] = useState(''); + + return ( + console.log('focus')} + onBlur={() => console.log('blur')} + > + setValue(e.target.value)} + placeholder="์ง€์ถœ ๋‚ด์—ญ" + textSize="bodyBold" + > + + setValue2(e.target.value)} + isFixed={true} + placeholder="0" + type="number" + style={{textAlign: 'right'}} + > + ์› + + + ); + }, +}; + +export const WithLabels: Story = { + render: ({...args}) => { + const [value, setValue] = useState(''); + const [value2, setValue2] = useState(''); + + return ( + console.log('focus')} + onBlur={() => console.log('blur')} + > + setValue(e.target.value)} + placeholder="์ง€์ถœ ๋‚ด์—ญ" + textSize="bodyBold" + > + + setValue2(e.target.value)} + placeholder="0" + type="number" + style={{textAlign: 'right'}} + > + ์› + + + ); + }, +}; + +export const ReadOnly: Story = { + render: ({...args}) => { + return ( + console.log('focus')} + onBlur={() => console.log('blur')} + > + + + + ์› + + + ); + }, +}; + +export const ReadOnlyWithIsFixedIcon: Story = { + render: ({...args}) => { + return ( + console.log('focus')} + onBlur={() => console.log('blur')} + > + + + + ์› + + + ); + }, +}; + +export const ListView: Story = { + render: ({...args}) => { + const LENGTH = 5; + const [valueList, setValueList] = useState(new Array(LENGTH).fill('')); + const [valueList2, setValueList2] = useState(new Array(LENGTH).fill('')); + + const handleValueListChange = (index: number, newValue: string) => { + const updatedList = [...valueList]; + updatedList[index] = newValue; + setValueList(updatedList); + }; + + const handleValueList2Change = (index: number, newValue: string) => { + const updatedList = [...valueList2]; + updatedList[index] = newValue; + setValueList2(updatedList); + }; + + return ( + console.log('focus')} + onBlur={() => console.log('blur')} + > + + {valueList.map((value, index) => ( + + handleValueListChange(index, e.target.value)} + placeholder="์ง€์ถœ ๋‚ด์—ญ" + textSize="bodyBold" + > + + handleValueList2Change(index, e.target.value)} + placeholder="0" + type="number" + style={{textAlign: 'right'}} + > + ์› + + + ))} + + + ); + }, +}; diff --git a/HDesign/src/components/EditableItem/EditableItem.style.ts b/HDesign/src/components/EditableItem/EditableItem.style.ts new file mode 100644 index 000000000..97142f2d8 --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.style.ts @@ -0,0 +1,21 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +export const editableItemStyle = (theme: Theme, backgroundColor: ColorKeys) => + css({ + display: 'flex', + justifyContent: 'space-between', + padding: '0.5rem 1rem', + borderRadius: '0.75rem', + backgroundColor: theme.colors[backgroundColor], + }); + +export const labelTextStyle = (theme: Theme, side: 'prefix' | 'suffix') => + css({ + color: theme.colors.gray, + paddingLeft: side === 'prefix' ? '0.375rem' : 0, + paddingRight: side === 'suffix' ? '0.375rem' : 0, + }); diff --git a/HDesign/src/components/EditableItem/EditableItem.tsx b/HDesign/src/components/EditableItem/EditableItem.tsx new file mode 100644 index 000000000..f8b9ca434 --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.tsx @@ -0,0 +1,54 @@ +/** @jsxImportSource @emotion/react */ +import Text from '@components/Text/Text'; +import Flex from '@components/Flex/Flex'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {editableItemStyle, labelTextStyle} from './EditableItem.style'; +import EditableItemInput from './EditableItem.Input'; +import {EditableItemProps} from './EditableItem.type'; +import {EditableItemProvider} from './EditableItem.context'; +import useEditableItem from './useEditableItem'; + +const EditableItemBase = ({ + onInputFocus, + onInputBlur, + prefixLabelText, + suffixLabelText, + backgroundColor = 'white', + children, + ...htmlProps +}: EditableItemProps) => { + const {theme} = useTheme(); + + useEditableItem({onInputFocus, onInputBlur}); + + return ( + + + + {prefixLabelText} + + + {suffixLabelText} + + + +
+ {children} +
+
+ ); +}; + +export const EditableItem = (props: EditableItemProps) => { + return ( + + + + ); +}; + +EditableItem.Input = EditableItemInput; + +export default EditableItem; diff --git a/HDesign/src/components/EditableItem/EditableItem.type.ts b/HDesign/src/components/EditableItem/EditableItem.type.ts new file mode 100644 index 000000000..a56835855 --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.type.ts @@ -0,0 +1,22 @@ +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +export interface EditableItemStyleProps { + backgroundColor?: ColorKeys; +} + +export interface EditableItemCustomProps { + onInputFocus?: () => void; + onInputBlur?: () => void; + prefixLabelText?: string; + suffixLabelText?: string; +} + +export interface EditableItemStylePropsWithTheme extends EditableItemStyleProps { + theme: Theme; +} + +export type EditableItemOptionProps = EditableItemStyleProps & EditableItemCustomProps; + +export type EditableItemProps = React.ComponentProps<'div'> & EditableItemOptionProps; diff --git a/HDesign/src/components/EditableItem/useEditableItem.ts b/HDesign/src/components/EditableItem/useEditableItem.ts new file mode 100644 index 000000000..86880deb6 --- /dev/null +++ b/HDesign/src/components/EditableItem/useEditableItem.ts @@ -0,0 +1,23 @@ +import {useEffect} from 'react'; + +import {useEditableItemContext} from './EditableItem.context'; + +interface UseEditableItemProps { + onInputFocus?: () => void; + onInputBlur?: () => void; +} + +const useEditableItem = ({onInputFocus, onInputBlur}: UseEditableItemProps) => { + const {hasAnyFocus} = useEditableItemContext(); + + useEffect(() => { + if (hasAnyFocus && onInputFocus) { + onInputFocus(); + } + if (!hasAnyFocus && onInputBlur) { + onInputBlur(); + } + }, [hasAnyFocus, onInputFocus, onInputBlur]); +}; + +export default useEditableItem; diff --git a/HDesign/src/components/EditableItem/useEditableItemInput.ts b/HDesign/src/components/EditableItem/useEditableItemInput.ts new file mode 100644 index 000000000..3253ad0ea --- /dev/null +++ b/HDesign/src/components/EditableItem/useEditableItemInput.ts @@ -0,0 +1,46 @@ +import {useCallback, useEffect, useState} from 'react'; + +import {useEditableItemContext} from './EditableItem.context'; + +interface UseEditableItemInputProps { + inputRef: React.RefObject; +} + +const useEditableItemInput = ({inputRef}: UseEditableItemInputProps) => { + const [hasFocus, setHasFocus] = useState(false); + const {setHasAnyFocus} = useEditableItemContext(); + + const handleFocus = useCallback(() => { + setHasFocus(true); + setHasAnyFocus(true); + }, [setHasAnyFocus]); + + const handleBlur = useCallback(() => { + setHasFocus(false); + setHasAnyFocus(false); + }, [setHasAnyFocus]); + + useEffect(() => { + const input = inputRef.current; + + if (input) { + input.addEventListener('focus', handleFocus); + input.addEventListener('blur', handleBlur); + + return () => { + input.removeEventListener('focus', handleFocus); + input.removeEventListener('blur', handleBlur); + }; + } + }, [handleFocus, handleBlur, inputRef]); + + useEffect(() => { + if (document.activeElement === inputRef.current) { + handleFocus(); + } + }, [handleFocus, inputRef]); + + return {hasFocus}; +}; + +export default useEditableItemInput; diff --git a/HDesign/src/components/ExpenseList/ExpenseList.stories.tsx b/HDesign/src/components/ExpenseList/ExpenseList.stories.tsx new file mode 100644 index 000000000..ccf8e28de --- /dev/null +++ b/HDesign/src/components/ExpenseList/ExpenseList.stories.tsx @@ -0,0 +1,29 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import ExpenseList from '@components/ExpenseList/ExpenseList'; + +const meta = { + title: 'Components/ExpenseList', + component: ExpenseList, + tags: ['autodocs'], + argTypes: { + expenseList: { + description: '', + }, + }, + args: { + expenseList: [ + {name: '์†Œํ•˜', price: 2000}, + {name: 'ํ† ๋‹ค๋ฆฌ', price: 2000}, + {name: '์›จ๋””', price: 1080}, + {name: '์ฟ ํ‚ค', price: 3020}, + ], + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/ExpenseList/ExpenseList.style.ts b/HDesign/src/components/ExpenseList/ExpenseList.style.ts new file mode 100644 index 000000000..8dbd227aa --- /dev/null +++ b/HDesign/src/components/ExpenseList/ExpenseList.style.ts @@ -0,0 +1,29 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +export const expenseItemStyle = () => + css({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + width: '100%', + height: '2.5rem', + padding: '0.5rem 1rem', + }); + +export const expenseItemLeftStyle = () => + css({ + display: 'flex', + alignItems: 'center', + gap: '1rem', + }); + +export const expenseListStyle = (theme: Theme) => + css({ + width: '100%', + backgroundColor: theme.colors.white, + padding: '0.5rem 0', + borderRadius: '1rem', + height: '100%', + }); diff --git a/HDesign/src/components/ExpenseList/ExpenseList.tsx b/HDesign/src/components/ExpenseList/ExpenseList.tsx new file mode 100644 index 000000000..1f57810e5 --- /dev/null +++ b/HDesign/src/components/ExpenseList/ExpenseList.tsx @@ -0,0 +1,37 @@ +/** @jsxImportSource @emotion/react */ + +import Text from '@components/Text/Text'; +import Icon from '@components/Icon/Icon'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {ExpenseItemProps, ExpenseListProps} from './ExpenseList.type'; +import {expenseItemStyle, expenseListStyle, expenseItemLeftStyle} from './ExpenseList.style'; + +// TODO: (@soha) ๋”ฐ๋กœ ํŒŒ์ผ ๋ถ„๋ฆฌํ• ๊นŒ ๊ณ ๋ฏผ์ค‘.. ์—ฌ๊ธฐ์„œ๋งŒ ์‚ฌ์šฉํ•  ๊ฒƒ ๊ฐ™๊ธด ํ•œ๋ฐ.. ํ  +// TODO: (@todari) : ์ถ”ํ›„ ํด๋ฆญ ์‹œ ์ƒํ˜ธ์ž‘์šฉ์ด ์ƒ๊ธฐ๋ฉด iconButton์œผ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Œ +function ExpenseItem({name, price, ...buttonProps}: ExpenseItemProps) { + const {theme} = useTheme(); + return ( + + ); +} + +function ExpenseList({expenseList = []}: ExpenseListProps) { + const {theme} = useTheme(); + return ( +
+ {expenseList.map(({name, price}, index: number) => ( + + ))} +
+ ); +} + +export default ExpenseList; diff --git a/HDesign/src/components/ExpenseList/ExpenseList.type.ts b/HDesign/src/components/ExpenseList/ExpenseList.type.ts new file mode 100644 index 000000000..939cd2f68 --- /dev/null +++ b/HDesign/src/components/ExpenseList/ExpenseList.type.ts @@ -0,0 +1,10 @@ +export interface ExpenseItemCustomProps { + name: string; + price: number; +} + +export type ExpenseItemProps = React.ComponentProps<'button'> & ExpenseItemCustomProps; + +export type ExpenseListProps = { + expenseList: ExpenseItemProps[]; +}; diff --git a/HDesign/src/components/FixedButton/FixedButton.stories.tsx b/HDesign/src/components/FixedButton/FixedButton.stories.tsx new file mode 100644 index 000000000..47485f851 --- /dev/null +++ b/HDesign/src/components/FixedButton/FixedButton.stories.tsx @@ -0,0 +1,46 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import FixedButton from '@components/FixedButton/FixedButton'; + +const meta = { + title: 'Components/FixedButton', + component: FixedButton, + tags: ['autodocs'], + parameters: {}, + argTypes: { + variants: { + description: '', + control: {type: 'select'}, + options: ['', 'primary', 'secondary', 'tertiary', 'loading'], + }, + disabled: { + description: '', + control: {type: 'boolean'}, + }, + onDeleteClick: { + description: '', + control: {type: 'select'}, + options: [undefined, () => alert('delete')], + }, + }, + args: { + variants: 'primary', + disabled: false, + children: 'button', + onDeleteClick: () => alert('delete'), + }, + decorators: [ + Story => ( +
+ +
+ ), + ], +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/FixedButton/FixedButton.style.ts b/HDesign/src/components/FixedButton/FixedButton.style.ts new file mode 100644 index 000000000..2e774918d --- /dev/null +++ b/HDesign/src/components/FixedButton/FixedButton.style.ts @@ -0,0 +1,127 @@ +import {css} from '@emotion/react'; + +import {ButtonVariants} from '@components/Button/Button.type'; +import {FixedButtonStyleProps} from '@components/FixedButton/FixedButton.type'; + +import {Theme} from '@theme/theme.type'; + +import {setDarker, setLighter} from '@utils/colors'; + +export const fixedButtonContainerStyle = (theme: Theme) => + css({ + display: 'flex', + position: 'fixed', + maxWidth: '768px', + inset: 'auto 0 0', + margin: '0 auto', + backgroundColor: theme.colors.white, + boxSizing: 'border-box', + }); + +export const buttonContainerStyle = css({ + display: 'flex', + gap: '1rem', + margin: '1rem 1rem 2rem 1rem', + width: '100%', +}); + +const getHoverAndActiveBackground = (color: string) => + css({ + ':not(:disabled)': { + '&:hover': { + backgroundColor: setLighter(color, 0.15), + }, + '&:active': { + backgroundColor: setDarker(color, 0.15), + }, + }, + }); + +export const deleteButtonStyle = (theme: Theme) => [ + css({ + display: 'flex', + justifyContent: 'center', + padding: '0.875rem 1rem', + borderRadius: '1.25rem', + backgroundColor: theme.colors.error, + color: theme.colors.white, + + fontFamily: 'Pretendard', + fontSize: '1rem', + fontWeight: '700', + lineHeight: '1', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + }), + getHoverAndActiveBackground(theme.colors.error), +]; + +export const fixedButtonStyle = (props: Required) => { + return [getFixedButtonDefaultStyle(props.theme), getFixedButtonVariantsStyle(props.variants, props.theme)]; +}; + +const getFixedButtonDefaultStyle = (theme: Theme) => + css({ + display: 'flex', + justifyContent: 'center', + padding: '1rem 1.5rem', + borderRadius: '1rem', + width: '100%', + + fontFamily: 'Pretendard', + fontSize: '1.25rem', + fontWeight: '700', + lineHeight: '1', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + + '&:disabled': { + backgroundColor: theme.colors.tertiary, + color: theme.colors.onPrimary, + cursor: 'default', + }, + }); + +const getFixedButtonVariantsStyle = (variants: ButtonVariants, theme: Theme) => { + const style = { + primary: [ + css({ + backgroundColor: theme.colors.primary, + color: theme.colors.onPrimary, + }), + getHoverAndActiveBackground(theme.colors.primary), + ], + secondary: [ + css({ + backgroundColor: theme.colors.secondary, + color: theme.colors.onSecondary, + }), + getHoverAndActiveBackground(theme.colors.secondary), + ], + tertiary: [ + css({ + backgroundColor: theme.colors.tertiary, + color: theme.colors.onTertiary, + }), + getHoverAndActiveBackground(theme.colors.tertiary), + ], + destructive: [ + css({ + backgroundColor: theme.colors.error, + color: theme.colors.onPrimary, + }), + getHoverAndActiveBackground(theme.colors.error), + ], + loading: [ + css({ + backgroundColor: theme.colors.tertiary, + color: theme.colors.onTertiary, + }), + getHoverAndActiveBackground(theme.colors.tertiary), + ], + }; + + return style[variants]; +}; diff --git a/HDesign/src/components/FixedButton/FixedButton.tsx b/HDesign/src/components/FixedButton/FixedButton.tsx new file mode 100644 index 000000000..4430016d6 --- /dev/null +++ b/HDesign/src/components/FixedButton/FixedButton.tsx @@ -0,0 +1,48 @@ +/** @jsxImportSource @emotion/react */ +import {forwardRef} from 'react'; +import Lottie from 'lottie-react'; + +import { + fixedButtonContainerStyle, + fixedButtonStyle, + buttonContainerStyle, +} from '@components/FixedButton/FixedButton.style'; +import {FixedButtonProps} from '@components/FixedButton/FixedButton.type'; +import IconButton from '@components/IconButton/IconButton'; +import Icon from '@components/Icon/Icon'; + +import loadingAnimation from '@assets/loadingAnimation.json'; + +import {useTheme} from '@theme/HDesignProvider'; + +export const FixedButton: React.FC = forwardRef(function Button( + {variants = 'primary', onDeleteClick, disabled, children, ...htmlProps}: FixedButtonProps, + ref, +) { + const {theme} = useTheme(); + return ( +
+
+ {onDeleteClick && ( + + + + )} + +
+
+ ); +}); + +export default FixedButton; diff --git a/HDesign/src/components/FixedButton/FixedButton.type.ts b/HDesign/src/components/FixedButton/FixedButton.type.ts new file mode 100644 index 000000000..1e8c55144 --- /dev/null +++ b/HDesign/src/components/FixedButton/FixedButton.type.ts @@ -0,0 +1,16 @@ +import {ButtonVariants} from '@components/Button/Button.type'; + +import {Theme} from '@theme/theme.type'; + +export interface FixedButtonStyleProps { + variants?: ButtonVariants; + theme?: Theme; +} + +export interface ButtonCustomProps { + onDeleteClick?: () => void; +} + +export type FixedButtonOptionProps = FixedButtonStyleProps & ButtonCustomProps; + +export type FixedButtonProps = React.ComponentProps<'button'> & FixedButtonOptionProps; diff --git a/HDesign/src/components/Flex/Flex.style.ts b/HDesign/src/components/Flex/Flex.style.ts new file mode 100644 index 000000000..672cf2dd6 --- /dev/null +++ b/HDesign/src/components/Flex/Flex.style.ts @@ -0,0 +1,49 @@ +import {css} from '@emotion/react'; + +import {changeCamelCaseToKebabCase} from '@utils/changeCamelCaseToKebabCase'; + +import {FlexDirectionStrictType, FlexProps} from './Flex.type'; + +export const flexStyle = ({ + justifyContent = 'flexStart', + alignItems = 'stretch', + flexDirection = 'row', + gap = '0', + padding = '0', + paddingInline = '0', + margin = '0', + width = 'auto', + height = 'auto', + minHeight, + backgroundColor, + theme, + ...rest +}: FlexProps) => + css({ + display: 'flex', + justifyContent: changeCamelCaseToKebabCase(justifyContent), + alignItems: changeCamelCaseToKebabCase(alignItems), + // TODO: (@weadie) as๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฐฉ๋ฒ•์ด ์—†์Œ. css์˜ flexDirection์†์„ฑ์€ string์„ ๋ฐ›์ง€ ์•Š๊ณ  ๋ช…ํ™•ํ•œ ์†์„ฑ๋ช…(ex row-reverse)๋ฅผ ๋ฐ›๊ณ  ์‹ถ์–ดํ•จ. ๋‹ค๋งŒ as๋ฅผ ์‚ฌ์šฉํ•ด๋„ ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•œ ๊ทผ๊ฑฐ๋Š” ์ผ€๋ฐฅํ•จ์ˆ˜๊ฐ€ FlexDirectionType์— ๋ช…์‹œ๋œ ๋ชจ๋“  ํƒ€์ž…์„ ์ •ํ™•ํ•˜๊ฒŒ ๋ณ€ํ™˜ํ•˜๋ฉฐ, ๋ฐ›๋Š” ๋ฌธ์ž์—ด์ด FlexDirectionType์— ์ œํ•œ๋˜๊ธฐ ๋•Œ๋ฌธ. + flexDirection: changeCamelCaseToKebabCase(flexDirection) as FlexDirectionStrictType, + gap, + padding, + paddingInline, + margin, + width, + height, + minHeight, + ...rest, + + backgroundColor: (() => { + switch (backgroundColor) { + case 'white': + return theme?.colors.white; + case 'gray': + return theme?.colors.grayContainer; + case 'lightGray': + return theme?.colors.lightGrayContainer; + default: + return 'none'; + } + })(), + }); diff --git a/HDesign/src/components/Flex/Flex.tsx b/HDesign/src/components/Flex/Flex.tsx new file mode 100644 index 000000000..26ce953f7 --- /dev/null +++ b/HDesign/src/components/Flex/Flex.tsx @@ -0,0 +1,17 @@ +/** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; + +import {StrictPropsWithChildren} from '@type/strictPropsWithChildren'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {FlexProps} from './Flex.type'; +import {flexStyle} from './Flex.style'; + +// TODO: (@weadie) ์ง€์ •๋œ ํ”„๋กญ ๋ง๊ณ  ๋‹ค๋ฅธ ํ”„๋กญ๋„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜์ž. +function Flex({children, ...props}: StrictPropsWithChildren) { + const {theme} = useTheme(); + return
{children}
; +} + +export default Flex; diff --git a/HDesign/src/components/Flex/Flex.type.ts b/HDesign/src/components/Flex/Flex.type.ts new file mode 100644 index 000000000..e70fb4c21 --- /dev/null +++ b/HDesign/src/components/Flex/Flex.type.ts @@ -0,0 +1,20 @@ +import {Theme} from '@theme/theme.type'; + +export type FlexDirectionType = 'row' | 'column' | 'rowReverse' | 'columnReverse'; +export type FlexDirectionStrictType = 'row' | 'column' | 'row-reverse' | 'column-reverse'; +export type FlexBackgroundColor = 'gray' | 'white' | 'lightGray'; + +export interface FlexProps { + justifyContent?: 'flexStart' | 'center' | 'flexEnd' | 'spaceBetween' | 'spaceAround' | 'spaceEvenly'; + alignItems?: 'flexStart' | 'center' | 'flexEnd' | 'stretch' | 'baseline'; + flexDirection?: FlexDirectionType; + gap?: string; + padding?: string; + paddingInline?: string; + margin?: string; + width?: string; + height?: string; + backgroundColor?: FlexBackgroundColor; + theme?: Theme; + minHeight?: string; +} diff --git a/HDesign/src/components/Icon/Icon.stories.tsx b/HDesign/src/components/Icon/Icon.stories.tsx new file mode 100644 index 000000000..3d2ef4aae --- /dev/null +++ b/HDesign/src/components/Icon/Icon.stories.tsx @@ -0,0 +1,28 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import Icon from '@components/Icon/Icon'; + +const meta = { + title: 'Components/Icon', + component: Icon, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + iconType: { + description: '', + control: {type: 'select'}, + options: ['inputDelete', 'buljusa', 'rightChevron', 'search', 'confirm', 'error', 'trash'], + }, + }, + args: { + iconType: 'rightChevron', + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Icon/Icon.style.ts b/HDesign/src/components/Icon/Icon.style.ts new file mode 100644 index 000000000..b19601da6 --- /dev/null +++ b/HDesign/src/components/Icon/Icon.style.ts @@ -0,0 +1,38 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +import {IconColor, IconStylePropsWithTheme, IconType} from './Icon.type'; + +const ICON_DEFAULT_COLOR: Record = { + inputDelete: 'gray', + buljusa: 'gray', + rightChevron: 'gray', + search: 'gray', + confirm: 'complete', + error: 'warn', + trash: 'white', +}; + +export const iconStyle = ({iconType, theme, iconColor}: IconStylePropsWithTheme) => { + return [ + css({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + }), + getIconColor({iconType, theme, iconColor}), + ]; +}; + +const getIconColor = ({iconType, theme, iconColor}: IconStylePropsWithTheme) => { + if (iconColor) { + return css({ + color: theme.colors[iconColor as ColorKeys], + }); + } else { + return css({color: theme.colors[ICON_DEFAULT_COLOR[iconType]]}); + } +}; diff --git a/HDesign/src/components/Icon/Icon.tsx b/HDesign/src/components/Icon/Icon.tsx new file mode 100644 index 000000000..13d8e7835 --- /dev/null +++ b/HDesign/src/components/Icon/Icon.tsx @@ -0,0 +1,29 @@ +/** @jsxImportSource @emotion/react */ + +import {IconProps} from '@components/Icon/Icon.type'; +import {InputDelete, Buljusa, RightChevron, Search, Trash, Confirm, Error} from '@assets'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {iconStyle} from './Icon.style'; + +const ICON = { + inputDelete: , + buljusa: , + rightChevron: , + search: , + error: , + confirm: , + trash: , +}; + +export const Icon: React.FC = ({iconColor, iconType, ...htmlProps}: IconProps) => { + const {theme} = useTheme(); + return ( +
+ {ICON[iconType]} +
+ ); +}; + +export default Icon; diff --git a/HDesign/src/components/Icon/Icon.type.ts b/HDesign/src/components/Icon/Icon.type.ts new file mode 100644 index 000000000..57fc25cfb --- /dev/null +++ b/HDesign/src/components/Icon/Icon.type.ts @@ -0,0 +1,21 @@ +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +export type IconType = 'inputDelete' | 'buljusa' | 'rightChevron' | 'search' | 'error' | 'confirm' | 'trash'; +export type IconColor = ColorKeys; + +export interface IconStyleProps { + iconColor?: IconColor; + iconType: IconType; +} + +export interface IconStylePropsWithTheme extends IconStyleProps { + theme: Theme; +} + +export interface IconCustomProps {} + +export type IconOptionProps = IconStyleProps & IconCustomProps; + +export type IconProps = React.ComponentProps<'div'> & IconOptionProps; diff --git a/HDesign/src/components/IconButton/IconButton.stories.tsx b/HDesign/src/components/IconButton/IconButton.stories.tsx new file mode 100644 index 000000000..6cc2b5f3d --- /dev/null +++ b/HDesign/src/components/IconButton/IconButton.stories.tsx @@ -0,0 +1,51 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import IconButton from '@components/IconButton/IconButton'; +import Icon from '@components/Icon/Icon'; + +const meta = { + title: 'Components/IconButton', + component: IconButton, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + size: { + description: '', + control: {type: 'select'}, + options: ['large', 'medium', 'small'], + }, + variants: { + description: '', + control: {type: 'select'}, + options: ['none', 'primary', 'secondary', 'tertiary', 'destructive'], + }, + children: { + description: '', + control: {type: 'select'}, + // TODO: (@todari) : Icon์˜ ์ƒ‰์ƒ์„ variants์— ์˜ํ•ด ์ž๋™์œผ๋กœ ๋ณ€๊ฒฝํ•ด ์ค„ ์ˆ˜ ์žˆ๋Š” ๋กœ์ง ์ถ”๊ฐ€ + options: [ + , + , + , + , + , + , + , + ], + }, + }, + args: { + size: 'medium', + variants: 'destructive', + children: , + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/IconButton/IconButton.style.ts b/HDesign/src/components/IconButton/IconButton.style.ts new file mode 100644 index 000000000..53036eb68 --- /dev/null +++ b/HDesign/src/components/IconButton/IconButton.style.ts @@ -0,0 +1,102 @@ +/** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +import {setDarker, setLighter} from '@utils/colors'; + +import { + IconButtonSize, + IconButtonStyleProps, + IconButtonStylePropsWithTheme, + IconButtonVariants, +} from './IconButton.type'; + +export const iconButtonStyle = ({theme, size = 'large', variants}: IconButtonStylePropsWithTheme) => { + if (variants === 'none') { + return 'none'; + } + return [getIconButtonBase(theme), getIconButtonSize(size), getIconButtonVariants({variants, theme})]; +}; + +const getHoverAndActiveBackground = (color: string) => + css({ + ':not(:disabled)': { + '&:hover': { + backgroundColor: setLighter(color, 0.15), + }, + '&:active': { + backgroundColor: setDarker(color, 0.15), + }, + }, + }); + +const getIconButtonBase = (theme: Theme) => + css({ + display: 'flex', + justifyContent: 'center', + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + whiteSpace: 'nowrap', + + '&:disabled': { + backgroundColor: theme.colors.tertiary, + color: theme.colors.onPrimary, + cursor: 'default', + }, + }); + +const getIconButtonSize = (size: IconButtonSize) => { + const style = { + small: css({ + padding: '0.5rem', + borderRadius: '0.75rem', + }), + medium: css({ + padding: '0.75rem', + borderRadius: '1rem', + }), + large: css({ + padding: '0.875rem', + borderRadius: '1.125rem', + }), + }; + + return style[size]; +}; + +const getIconButtonVariants = ({variants, theme}: IconButtonStylePropsWithTheme) => { + const style = { + none: [css({})], + primary: [ + css({ + backgroundColor: theme.colors.primary, + color: theme.colors.onPrimary, + }), + getHoverAndActiveBackground(theme.colors.primary), + ], + secondary: [ + css({ + backgroundColor: theme.colors.secondary, + color: theme.colors.onSecondary, + }), + getHoverAndActiveBackground(theme.colors.secondary), + ], + tertiary: [ + css({ + backgroundColor: theme.colors.tertiary, + color: theme.colors.onTertiary, + }), + getHoverAndActiveBackground(theme.colors.tertiary), + ], + destructive: [ + css({ + backgroundColor: theme.colors.error, + color: theme.colors.onPrimary, + }), + getHoverAndActiveBackground(theme.colors.error), + ], + }; + + return style[variants]; +}; diff --git a/HDesign/src/components/IconButton/IconButton.tsx b/HDesign/src/components/IconButton/IconButton.tsx new file mode 100644 index 000000000..bc704db67 --- /dev/null +++ b/HDesign/src/components/IconButton/IconButton.tsx @@ -0,0 +1,22 @@ +/** @jsxImportSource @emotion/react */ +import {forwardRef} from 'react'; + +import {IconButtonProps} from '@components/IconButton/IconButton.type'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {iconButtonStyle} from './IconButton.style'; + +export const IconButton: React.FC = forwardRef(function Button( + {size, variants, children, ...htmlProps}: IconButtonProps, + ref, +) { + const {theme} = useTheme(); + return ( + + ); +}); + +export default IconButton; diff --git a/HDesign/src/components/IconButton/IconButton.type.ts b/HDesign/src/components/IconButton/IconButton.type.ts new file mode 100644 index 000000000..de891e0ba --- /dev/null +++ b/HDesign/src/components/IconButton/IconButton.type.ts @@ -0,0 +1,19 @@ +import {Theme} from '@theme/theme.type'; + +export type IconButtonSize = 'large' | 'medium' | 'small'; +export type IconButtonVariants = 'none' | 'primary' | 'secondary' | 'tertiary' | 'destructive'; + +export interface IconButtonStyleProps { + size?: IconButtonSize; + variants: IconButtonVariants; +} + +export interface IconButtonStylePropsWithTheme extends IconButtonStyleProps { + theme: Theme; +} + +export interface IconButtonCustomProps {} + +export type IconButtonOptionProps = IconButtonStyleProps & IconButtonCustomProps; + +export type IconButtonProps = React.ComponentProps<'button'> & IconButtonOptionProps; diff --git a/HDesign/src/components/Input/Input.stories.tsx b/HDesign/src/components/Input/Input.stories.tsx new file mode 100644 index 000000000..dc46e022f --- /dev/null +++ b/HDesign/src/components/Input/Input.stories.tsx @@ -0,0 +1,56 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import React, {useEffect, useState} from 'react'; + +import Input from '@components/Input/Input'; +import Flex from '@components/Flex/Flex'; +import Button from '@components/Button/Button'; + +const meta = { + title: 'Components/Input', + component: Input, + tags: ['autodocs'], + argTypes: { + inputType: { + // TODO: (@cookie) ์Šคํ† ๋ฆฌ๋ถ ๋ผ๋””์˜ค๋ฒ„ํŠผ ๋ณด์ด๋„๋ก ์„ค์ •ํ•ด์•ผ ํ•จ + control: {type: 'radio'}, + }, + }, + args: { + placeholder: 'placeholder', + autoFocus: true, + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = { + render: ({...args}) => { + const regex = /^[ใ„ฑ-ใ…Ž๊ฐ€-ํžฃ]*$/; + const [value, setValue] = useState(''); + const [isError, setIsError] = useState(false); + + const handleChange = (event: React.ChangeEvent) => { + const newValue = event.target.value; + if (regex.test(newValue)) { + setValue(newValue); + setIsError(false); + } else { + setIsError(true); + } + }; + + const changeRandomValue = () => { + setValue('์™ธ๋ถ€์—์„œ ๊ฐ’ ๋ณ€๊ฒฝ๋จ'); + }; + + return ( +
+ + +
+ ); + }, +}; diff --git a/HDesign/src/components/Input/Input.style.ts b/HDesign/src/components/Input/Input.style.ts new file mode 100644 index 000000000..a9ddff89d --- /dev/null +++ b/HDesign/src/components/Input/Input.style.ts @@ -0,0 +1,56 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +import {InputType} from './Input.type'; + +const getBackgroundColorStyle = (theme: Theme, inputType: InputType = 'input') => { + switch (inputType) { + case 'input': + return theme.colors.lightGrayContainer; + + case 'search': + return theme.colors.white; + + default: + return theme.colors.lightGrayContainer; + } +}; + +const getBorderStyle = (isFocus: boolean, theme: Theme, isError?: boolean) => + isError ? `0 0 0 1px ${theme.colors.error} inset` : isFocus ? `0 0 0 1px ${theme.colors.primary} inset` : 'none'; + +export const inputBoxStyle = ( + theme: Theme, + inputType: InputType = 'input', + isFocus: boolean, + isError: boolean | undefined, +) => + css({ + display: 'flex', + justifyContent: 'space-between', + gap: '1rem', + padding: '0.75rem 1rem', + borderRadius: '1rem', + backgroundColor: getBackgroundColorStyle(theme, inputType), + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + + boxSizing: 'border-box', + boxShadow: getBorderStyle(isFocus, theme, isError), + }); + +export const inputStyle = (theme: Theme) => + css( + { + display: 'flex', + width: '100%', + color: theme.colors.black, + + '&:placeholder': { + color: theme.colors.gray, + }, + }, + theme.typography.body, + ); diff --git a/HDesign/src/components/Input/Input.tsx b/HDesign/src/components/Input/Input.tsx new file mode 100644 index 000000000..37945e434 --- /dev/null +++ b/HDesign/src/components/Input/Input.tsx @@ -0,0 +1,51 @@ +/** @jsxImportSource @emotion/react */ +import React, {forwardRef, useImperativeHandle, useRef} from 'react'; + +import IconButton from '@components/IconButton/IconButton'; +import {InputProps} from '@components/Input/Input.type'; +import {inputBoxStyle, inputStyle} from '@components/Input/Input.style'; +import {useInput} from '@components/Input/useInput'; +import Icon from '@components/Icon/Icon'; + +import {useTheme} from '@theme/HDesignProvider'; + +export const Input: React.FC = forwardRef(function Input( + {value: propsValue, onChange, onFocus, onBlur, inputType, isError, placeholder, autoFocus, ...htmlProps}: InputProps, + ref, +) { + const {theme} = useTheme(); + const inputRef = useRef(null); + const {value, handleChange, hasFocus, handleClickDelete, handleBlur, handleFocus, handleKeyDown} = useInput({ + propsValue, + onChange, + onBlur, + onFocus, + inputRef, + autoFocus, + }); + useImperativeHandle(ref, () => inputRef.current!); + + return ( +
+ + {value && hasFocus && ( + + + + )} +
+ ); +}); + +export default Input; diff --git a/HDesign/src/components/Input/Input.type.ts b/HDesign/src/components/Input/Input.type.ts new file mode 100644 index 000000000..2cfdfcd4a --- /dev/null +++ b/HDesign/src/components/Input/Input.type.ts @@ -0,0 +1,16 @@ +import {Theme} from '@theme/theme.type'; + +export interface InputStyleProps { + theme?: Theme; +} + +export type InputType = 'input' | 'search'; + +export interface InputCustomProps { + inputType?: InputType; + isError?: boolean; +} + +export type InputOptionProps = InputStyleProps & InputCustomProps; + +export type InputProps = React.ComponentProps<'input'> & InputOptionProps; diff --git a/HDesign/src/components/Input/useInput.ts b/HDesign/src/components/Input/useInput.ts new file mode 100644 index 000000000..a9e531a07 --- /dev/null +++ b/HDesign/src/components/Input/useInput.ts @@ -0,0 +1,71 @@ +import {RefObject, useEffect, useState} from 'react'; + +interface UseInputProps { + propsValue: T; + onChange?: (e: React.ChangeEvent) => void; + onFocus?: (event: React.FocusEvent) => void; + onBlur?: (event: React.FocusEvent) => void; + inputRef: RefObject; + autoFocus?: boolean; +} + +export const useInput = ({propsValue, onChange, onBlur, onFocus, autoFocus, inputRef}: UseInputProps) => { + const [value, setValue] = useState(propsValue); + const [hasFocus, setHasFocus] = useState(inputRef.current === document.activeElement); + + useEffect(() => { + if (autoFocus && inputRef.current) { + inputRef.current.focus(); + setHasFocus(true); + } + }, [autoFocus, inputRef]); + + useEffect(() => { + setValue(propsValue); + }, [propsValue, value]); + + const handleClickDelete = (event: React.MouseEvent) => { + event.preventDefault(); + setValue('' as T); + if (onChange) { + onChange({target: {value: ''}} as React.ChangeEvent); + } + if (inputRef.current) { + inputRef.current.focus(); + } + }; + + const handleChange = (e: React.ChangeEvent) => { + setValue(e.target.value as T); + if (onChange) { + onChange(e); + } + }; + + const handleBlur = (e: React.FocusEvent) => { + setHasFocus(false); + if (onBlur) { + onBlur(e); + } + }; + + const handleFocus = (e: React.FocusEvent) => { + setHasFocus(true); + if (onFocus) { + onFocus(e); + } + }; + + const handleKeyDown = (event: React.KeyboardEvent) => { + if (event.nativeEvent.isComposing) return; + + if (event.key === 'Enter' || event.key === 'Escape') { + setHasFocus(false); + if (inputRef.current) { + inputRef.current.blur(); + } + } + }; + + return {value, handleChange, hasFocus, handleClickDelete, handleBlur, handleFocus, handleKeyDown}; +}; diff --git a/HDesign/src/components/IsFixedIcon/IsFixedIcon.style.ts b/HDesign/src/components/IsFixedIcon/IsFixedIcon.style.ts new file mode 100644 index 000000000..6ba001e05 --- /dev/null +++ b/HDesign/src/components/IsFixedIcon/IsFixedIcon.style.ts @@ -0,0 +1,9 @@ +import {css} from '@emotion/react'; + +import {WithTheme} from '@type/withTheme'; + +export const isFixedIconStyle = ({theme}: WithTheme) => + css({ + color: theme.colors.error, + paddingRight: '0.25rem', + }); diff --git a/HDesign/src/components/IsFixedIcon/IsFixedIcon.tsx b/HDesign/src/components/IsFixedIcon/IsFixedIcon.tsx new file mode 100644 index 000000000..a7b62d959 --- /dev/null +++ b/HDesign/src/components/IsFixedIcon/IsFixedIcon.tsx @@ -0,0 +1,13 @@ +/** @jsxImportSource @emotion/react */ + +import {useTheme} from '@theme/HDesignProvider'; + +import {isFixedIconStyle} from './IsFixedIcon.style'; + +const IsFixedIcon = () => { + const {theme} = useTheme(); + + return
*
; +}; + +export default IsFixedIcon; diff --git a/HDesign/src/components/LabelGroupInput/Element.tsx b/HDesign/src/components/LabelGroupInput/Element.tsx new file mode 100644 index 000000000..5ffd852bd --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/Element.tsx @@ -0,0 +1,63 @@ +/** @jsxImportSource @emotion/react */ + +import {forwardRef, useEffect, useImperativeHandle, useRef, useState} from 'react'; + +import Input from '../Input/Input'; + +import {ElementProps} from './Element.type'; +import {useGroupInputContext} from './GroupInputContext'; + +const Element: React.FC = forwardRef(function Element( + {elementKey, value: propsValue, onChange, onBlur, onFocus, isError, autoFocus, ...htmlProps}: ElementProps, + + ref, +) { + useImperativeHandle(ref, () => inputRef.current!); + const inputRef = useRef(null); + const {setHasAnyFocus, values, setValues, errors, setErrors} = useGroupInputContext(); + + useEffect(() => { + setValues({...values, [elementKey]: `${propsValue}`}); + }, [propsValue]); + + const handleChange = (e: React.ChangeEvent) => { + const newValue = e.target.value; + setValues({...values, [elementKey]: newValue}); + if (onChange) { + onChange(e); + } + }; + + useEffect(() => { + setErrors({...errors, [elementKey]: isError ?? false}); + }, [isError]); + + const handleBlur = (e: React.FocusEvent) => { + setHasAnyFocus(false); + if (onBlur) { + onBlur(e); + } + }; + + const handleFocus = (e: React.FocusEvent) => { + setHasAnyFocus(true); + if (onFocus) { + onFocus(e); + } + }; + + return ( + + ); +}); + +export default Element; diff --git a/HDesign/src/components/LabelGroupInput/Element.type.ts b/HDesign/src/components/LabelGroupInput/Element.type.ts new file mode 100644 index 000000000..2ec2ef9ed --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/Element.type.ts @@ -0,0 +1,10 @@ +export interface ElementStyleProps {} + +export interface ElementCustomProps { + elementKey: string; + isError?: boolean; +} + +export type ElementOptionProps = ElementStyleProps & ElementCustomProps; + +export type ElementProps = React.ComponentProps<'input'> & ElementOptionProps; diff --git a/HDesign/src/components/LabelGroupInput/GroupInputContext.tsx b/HDesign/src/components/LabelGroupInput/GroupInputContext.tsx new file mode 100644 index 000000000..142183e6b --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/GroupInputContext.tsx @@ -0,0 +1,32 @@ +import React, {createContext, PropsWithChildren, useContext, useState} from 'react'; + +interface GroupInputContextProps { + hasAnyFocus: boolean; + setHasAnyFocus: React.Dispatch>; + values: {[key: string]: string}; + setValues: React.Dispatch>; + errors: {[key: string]: boolean}; + setErrors: React.Dispatch>; +} + +const GroupInputContext = createContext(undefined); + +export const useGroupInputContext = () => { + const context = useContext(GroupInputContext); + if (!context) { + throw new Error('useGroupInputContext must be used within an GroupInputProvider'); + } + return context; +}; + +export const GroupInputProvider: React.FC = ({children}: React.PropsWithChildren) => { + const [hasAnyFocus, setHasAnyFocus] = useState(false); + const [values, setValues] = useState<{[key: string]: string}>({}); + const [errors, setErrors] = useState<{[key: string]: boolean}>({}); + + return ( + + {children} + + ); +}; diff --git a/HDesign/src/components/LabelGroupInput/LabelGroupInput.stories.tsx b/HDesign/src/components/LabelGroupInput/LabelGroupInput.stories.tsx new file mode 100644 index 000000000..4eec9634f --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/LabelGroupInput.stories.tsx @@ -0,0 +1,75 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import {useState} from 'react'; + +import LabelGroupInput from '@components/LabelGroupInput/LabelGroupInput'; + +const meta = { + title: 'Components/LabelGroupInput', + component: LabelGroupInput, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: { + labelText: { + description: 'label์— ๋“ค์–ด๊ฐˆ ํ…์ŠคํŠธ๋ฅผ ์ž‘์„ฑ', + control: {type: 'text'}, + }, + errorText: { + description: 'error์— ๋“ค์–ด๊ฐˆ ํ…์ŠคํŠธ๋ฅผ ์ž‘์„ฑ', + control: {type: 'text'}, + }, + }, + args: { + labelText: '์ง€์ถœ๋‚ด์—ญ / ๊ธˆ์•ก', + errorText: 'error๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค!', + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = { + render: ({...args}) => { + const [name, setName] = useState(''); + const [price, setPrice] = useState(''); + const [isError, setIsError] = useState(false); + const handleChangeName = (event: React.ChangeEvent) => { + if (event.target.value.length < 4) { + setName(event.target.value); + setIsError(false); + } else { + event.target.value = name; + setIsError(true); + } + }; + const handleChangePrice = (event: React.ChangeEvent) => { + setPrice(event.target.value); + }; + return ( + + handleChangeName(e)} + onBlur={() => console.log('!!!')} + isError={isError} + autoFocus + /> + console.log('!!!')} + isError={false} + autoFocus + /> + + ); + }, +}; diff --git a/HDesign/src/components/LabelGroupInput/LabelGroupInput.style.ts b/HDesign/src/components/LabelGroupInput/LabelGroupInput.style.ts new file mode 100644 index 000000000..8339ef4a4 --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/LabelGroupInput.style.ts @@ -0,0 +1,25 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@/theme/theme.type'; + +export const labelTextStyle = (theme: Theme, hasFocus: boolean, hasValue: boolean) => + css({ + height: '1.125rem', + color: theme.colors.gray, + + opacity: hasFocus || hasValue ? '1' : '0', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + }); + +export const errorTextStyle = (theme: Theme, isError: boolean) => + css({ + height: '1.125rem', + color: theme.colors.onErrorContainer, + + opacity: isError ? '1' : '0', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + }); diff --git a/HDesign/src/components/LabelGroupInput/LabelGroupInput.tsx b/HDesign/src/components/LabelGroupInput/LabelGroupInput.tsx new file mode 100644 index 000000000..33d1d447d --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/LabelGroupInput.tsx @@ -0,0 +1,48 @@ +/** @jsxImportSource @emotion/react */ + +import Text from '@components/Text/Text'; + +import {useTheme} from '@theme/HDesignProvider'; + +import Flex from '../Flex/Flex'; + +import {LabelGroupInputProps} from './LabelGroupInput.type'; +import {errorTextStyle, labelTextStyle} from './LabelGroupInput.style'; +import Element from './Element'; +import {GroupInputProvider, useGroupInputContext} from './GroupInputContext'; + +const LabelGroupInput: React.FC = ({labelText, errorText, children}: LabelGroupInputProps) => { + const {theme} = useTheme(); + const {hasAnyFocus, values, errors} = useGroupInputContext(); + + const hasAnyValue = !Object.values(values).every(value => value === ''); + const hasAnyError = !Object.values(errors).every(error => !error); + + return ( + + + + {labelText} + + {errorText && ( + + {errorText} + + )} + + + {children} + + + ); +}; + +const LabelGroupInputContainer = (props: LabelGroupInputProps) => ( + + + +); + +LabelGroupInputContainer.Element = Element; + +export default LabelGroupInputContainer; diff --git a/HDesign/src/components/LabelGroupInput/LabelGroupInput.type.ts b/HDesign/src/components/LabelGroupInput/LabelGroupInput.type.ts new file mode 100644 index 000000000..8507311b5 --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/LabelGroupInput.type.ts @@ -0,0 +1,10 @@ +export interface LabelGroupInputStyleProps {} + +export interface LabelGroupInputCustomProps { + labelText: string; + errorText: string | null; +} + +export type LabelGroupInputOptionProps = LabelGroupInputStyleProps & LabelGroupInputCustomProps; + +export type LabelGroupInputProps = React.ComponentProps<'input'> & LabelGroupInputOptionProps; diff --git a/HDesign/src/components/LabelGroupInput/index.ts b/HDesign/src/components/LabelGroupInput/index.ts new file mode 100644 index 000000000..c31f35eaf --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/index.ts @@ -0,0 +1,3 @@ +import LabelGroupInputContainer from './LabelGroupInput'; + +export {LabelGroupInputContainer as LabelGroupInput}; diff --git a/HDesign/src/components/LabelInput/LabelInput.stories.tsx b/HDesign/src/components/LabelInput/LabelInput.stories.tsx new file mode 100644 index 000000000..a272037a4 --- /dev/null +++ b/HDesign/src/components/LabelInput/LabelInput.stories.tsx @@ -0,0 +1,56 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import {useEffect, useState} from 'react'; + +import LabelInput from '@components/LabelInput/LabelInput'; + +const meta = { + title: 'Components/LabelInput', + component: LabelInput, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: { + labelText: { + description: 'label์— ๋“ค์–ด๊ฐˆ ํ…์ŠคํŠธ๋ฅผ ์ž‘์„ฑ', + control: {type: 'text'}, + }, + isError: { + description: '', + control: {type: 'boolean'}, + }, + errorText: { + description: 'error์— ๋“ค์–ด๊ฐˆ ํ…์ŠคํŠธ๋ฅผ ์ž‘์„ฑ', + control: {type: 'text'}, + }, + }, + args: { + // value: '', + labelText: '์ด๋ฆ„', + errorText: 'error๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค!', + autoFocus: true, + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = { + render: ({...args}) => { + const [value, setValue] = useState(''); + const [isError, setIsError] = useState(false); + const handleChange = (event: React.ChangeEvent) => { + if (event.target.value.length < 4) { + setValue(event.target.value); + setIsError(false); + } else { + event.target.value = value; + setIsError(true); + } + }; + return handleChange(e)} isError={isError} {...args} />; + }, +}; diff --git a/HDesign/src/components/LabelInput/LabelInput.style.ts b/HDesign/src/components/LabelInput/LabelInput.style.ts new file mode 100644 index 000000000..df64636e9 --- /dev/null +++ b/HDesign/src/components/LabelInput/LabelInput.style.ts @@ -0,0 +1,25 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +export const labelTextStyle = (theme: Theme, hasFocus: boolean, hasValue: boolean) => + css({ + height: '1.125rem', + color: theme.colors.gray, + + opacity: hasFocus || hasValue ? '1' : '0', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + }); + +export const errorTextStyle = (theme: Theme, isError: boolean) => + css({ + height: '1.125rem', + color: theme.colors.onErrorContainer, + + opacity: isError ? '1' : '0', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + }); diff --git a/HDesign/src/components/LabelInput/LabelInput.tsx b/HDesign/src/components/LabelInput/LabelInput.tsx new file mode 100644 index 000000000..43f60c220 --- /dev/null +++ b/HDesign/src/components/LabelInput/LabelInput.tsx @@ -0,0 +1,45 @@ +/** @jsxImportSource @emotion/react */ + +import {forwardRef, useImperativeHandle, useRef} from 'react'; + +import Text from '@components/Text/Text'; + +import {useTheme} from '@theme/HDesignProvider'; + +import Input from '../Input/Input'; +import Flex from '../Flex/Flex'; + +import {errorTextStyle, labelTextStyle} from './LabelInput.style'; +import {useLabelInput} from './useLabelInput'; +import {LabelInputProps} from './LabelInput.type'; + +const LabelInput: React.FC = forwardRef(function LabelInput( + {labelText, errorText, isError, ...htmlProps}: LabelInputProps, + ref, +) { + useImperativeHandle(ref, () => inputRef.current!); + + const {theme} = useTheme(); + const inputRef = useRef(null); + const {hasFocus} = useLabelInput({inputRef}); + + return ( + + + + {labelText} + + {errorText && ( + + {errorText} + + )} + + + + + + ); +}); + +export default LabelInput; diff --git a/HDesign/src/components/LabelInput/LabelInput.type.ts b/HDesign/src/components/LabelInput/LabelInput.type.ts new file mode 100644 index 000000000..83e7e9751 --- /dev/null +++ b/HDesign/src/components/LabelInput/LabelInput.type.ts @@ -0,0 +1,12 @@ +export interface LabelInputStyleProps {} + +export interface LabelInputCustomProps { + labelText: string; + errorText: string | null; + isError?: boolean; + autoFocus: boolean; +} + +export type LabelInputOptionProps = LabelInputCustomProps & LabelInputCustomProps; + +export type LabelInputProps = React.ComponentProps<'input'> & LabelInputOptionProps; diff --git a/HDesign/src/components/LabelInput/useLabelInput.ts b/HDesign/src/components/LabelInput/useLabelInput.ts new file mode 100644 index 000000000..e967c5f89 --- /dev/null +++ b/HDesign/src/components/LabelInput/useLabelInput.ts @@ -0,0 +1,26 @@ +import {RefObject, useEffect, useState} from 'react'; + +interface UseLabelInput { + inputRef: RefObject; + autoFocus?: boolean; +} + +export const useLabelInput = ({inputRef, autoFocus}: UseLabelInput) => { + const [hasFocus, setHasFocus] = useState(inputRef.current === document.activeElement); + + useEffect(() => { + setHasFocus(inputRef.current === document.activeElement); + }, []); + + useEffect(() => { + inputRef.current?.addEventListener('focus', () => setHasFocus(true)); + inputRef.current?.addEventListener('blur', () => setHasFocus(false)); + + return () => { + inputRef.current?.removeEventListener('focus', () => setHasFocus(true)); + inputRef.current?.removeEventListener('blur', () => setHasFocus(false)); + }; + }, []); + + return {hasFocus}; +}; diff --git a/HDesign/src/components/ListButton/ListButton.stories.tsx b/HDesign/src/components/ListButton/ListButton.stories.tsx new file mode 100644 index 000000000..27f7744d1 --- /dev/null +++ b/HDesign/src/components/ListButton/ListButton.stories.tsx @@ -0,0 +1,32 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import ListButton from '@components/ListButton/ListButton'; + +const meta = { + title: 'Components/ListButton', + component: ListButton, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: { + prefix: { + description: '', + control: {type: 'text'}, + }, + suffix: { + description: '', + control: {type: 'text'}, + }, + }, + args: { + prefix: '์ „์ฒด ์ฐธ์—ฌ์ž', + suffix: '7๋ช…', + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/ListButton/ListButton.style.ts b/HDesign/src/components/ListButton/ListButton.style.ts new file mode 100644 index 000000000..fcca0ca01 --- /dev/null +++ b/HDesign/src/components/ListButton/ListButton.style.ts @@ -0,0 +1,16 @@ +/** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +export const listButtonStyle = (theme: Theme) => + css({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + width: '100%', + padding: '0.375rem 1rem', + backgroundColor: theme.colors.white, + + boxShadow: `0 1px 0 0 ${theme.colors.grayContainer} inset `, + }); diff --git a/HDesign/src/components/ListButton/ListButton.tsx b/HDesign/src/components/ListButton/ListButton.tsx new file mode 100644 index 000000000..10c417310 --- /dev/null +++ b/HDesign/src/components/ListButton/ListButton.tsx @@ -0,0 +1,36 @@ +/** @jsxImportSource @emotion/react */ +import React, {forwardRef} from 'react'; + +import Text from '@components/Text/Text'; +import IconButton from '@components/IconButton/IconButton'; +import Flex from '@components/Flex/Flex'; +import Icon from '@components/Icon/Icon'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {ListButtonProps} from './ListButton.type'; +import {listButtonStyle} from './ListButton.style'; + +export const ListButton: React.FC = forwardRef(function Button( + {prefix, suffix, ...htmlProps}: ListButtonProps, + ref, +) { + const {theme} = useTheme(); + return ( + + ); +}); + +export default ListButton; diff --git a/HDesign/src/components/ListButton/ListButton.type.ts b/HDesign/src/components/ListButton/ListButton.type.ts new file mode 100644 index 000000000..788117870 --- /dev/null +++ b/HDesign/src/components/ListButton/ListButton.type.ts @@ -0,0 +1,10 @@ +export interface ListButtonStyleProps {} + +export interface ListButtonCustomProps { + prefix?: string; + suffix?: string; +} + +export type ListButtonOptionProps = ListButtonStyleProps & ListButtonCustomProps; + +export type ListButtonProps = React.ComponentProps<'button'> & ListButtonOptionProps; diff --git a/HDesign/src/components/Search/Search.stories.tsx b/HDesign/src/components/Search/Search.stories.tsx new file mode 100644 index 000000000..6b5d821cd --- /dev/null +++ b/HDesign/src/components/Search/Search.stories.tsx @@ -0,0 +1,32 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import React from 'react'; + +import Search from '@components/Search/Search'; + +const meta = { + title: 'Components/Search', + component: Search, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + decorators: [ + Story => ( +
+ +
+ ), + ], + args: { + isShowTargetInput: true, + matchItems: ['todari', 'cookie'], + onMatchItemClick: keyword => alert(keyword), + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Search/Search.style.ts b/HDesign/src/components/Search/Search.style.ts new file mode 100644 index 000000000..d75e8fe25 --- /dev/null +++ b/HDesign/src/components/Search/Search.style.ts @@ -0,0 +1,42 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +export const searchStyle = css({ + position: 'relative', + + width: '100%', +}); + +export const searchTermsStyle = (theme: Theme) => + css({ + position: 'absolute', + top: '3.5rem', + zIndex: 1, + + width: '100%', + padding: '0.5rem 1rem', + + borderRadius: '1rem', + + backgroundColor: theme.colors.white, + + boxShadow: '0 0.25rem 0.5rem 0 rgba(0, 0, 0, 0.12)', + }); + +export const searchTermStyle = (theme: Theme) => + css( + { + width: '100%', + padding: '0.5rem', + + color: theme.colors.onTertiary, + + '&:hover': { + borderRadius: '0.5rem', + + backgroundColor: theme.colors.lightGrayContainer, + }, + }, + theme.typography.body, + ); diff --git a/HDesign/src/components/Search/Search.tsx b/HDesign/src/components/Search/Search.tsx new file mode 100644 index 000000000..58c292cc4 --- /dev/null +++ b/HDesign/src/components/Search/Search.tsx @@ -0,0 +1,37 @@ +/** @jsxImportSource @emotion/react */ +import Flex from '@components/Flex/Flex'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {searchStyle, searchTermsStyle, searchTermStyle} from './Search.style'; + +export interface SearchProps { + isShowTargetInput: boolean; + matchItems: string[]; + onMatchItemClick: (term: string) => void; +} + +const Search = ({isShowTargetInput, matchItems, onMatchItemClick, children}: React.PropsWithChildren) => { + const {theme} = useTheme(); + + return ( +
+ {children} + {matchItems.length > 0 && isShowTargetInput && ( +
    + + {matchItems.map((matchItem, index) => ( +
  • + +
  • + ))} +
    +
+ )} +
+ ); +}; + +export default Search; diff --git a/HDesign/src/components/Switch/Switch.stories.tsx b/HDesign/src/components/Switch/Switch.stories.tsx new file mode 100644 index 000000000..a3558754a --- /dev/null +++ b/HDesign/src/components/Switch/Switch.stories.tsx @@ -0,0 +1,35 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import Switch from '@components/Switch/Switch'; + +const meta = { + title: 'Components/Switch', + component: Switch, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + value: { + description: '', + control: {type: 'select', options: ['ํ™ˆ', '๊ด€๋ฆฌ']}, + }, + values: { + description: '', + }, + onChange: { + description: '', + }, + }, + args: { + value: 'ํ™ˆ', + values: ['ํ™ˆ', '๊ด€๋ฆฌ'], + onChange: value => alert(`${value} ์„ ํƒ๋จ`), + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Switch/Switch.style.ts b/HDesign/src/components/Switch/Switch.style.ts new file mode 100644 index 000000000..d88c18748 --- /dev/null +++ b/HDesign/src/components/Switch/Switch.style.ts @@ -0,0 +1,6 @@ +import {css} from '@emotion/react'; + +export const switchContainerStyle = css({ + display: 'flex', + gap: '0.75rem', +}); diff --git a/HDesign/src/components/Switch/Switch.tsx b/HDesign/src/components/Switch/Switch.tsx new file mode 100644 index 000000000..4a1275185 --- /dev/null +++ b/HDesign/src/components/Switch/Switch.tsx @@ -0,0 +1,24 @@ +/** @jsxImportSource @emotion/react */ +import TextButton from '../TextButton/TextButton'; + +import {switchContainerStyle} from './Switch.style'; +import {SwitchProps} from './Switch.type'; + +function Switch({value, values, onChange}: SwitchProps) { + return ( +
+ {values.map((item, index) => ( + onChange(values[index])} + > + {item} + + ))} +
+ ); +} + +export default Switch; diff --git a/HDesign/src/components/Switch/Switch.type.ts b/HDesign/src/components/Switch/Switch.type.ts new file mode 100644 index 000000000..7e0d31d0f --- /dev/null +++ b/HDesign/src/components/Switch/Switch.type.ts @@ -0,0 +1,5 @@ +export interface SwitchProps { + value: string; + values: string[]; + onChange: (value: string) => void; +} diff --git a/HDesign/src/components/Tabs/Tab.tsx b/HDesign/src/components/Tabs/Tab.tsx new file mode 100644 index 000000000..2a79c1b78 --- /dev/null +++ b/HDesign/src/components/Tabs/Tab.tsx @@ -0,0 +1,8 @@ +/** @jsxImportSource @emotion/react */ +import {TabProps} from './Tab.type'; + +const Tab: React.FC = () => { + return <>; +}; + +export default Tab; diff --git a/HDesign/src/components/Tabs/Tab.type.ts b/HDesign/src/components/Tabs/Tab.type.ts new file mode 100644 index 000000000..6b9e4972e --- /dev/null +++ b/HDesign/src/components/Tabs/Tab.type.ts @@ -0,0 +1,16 @@ +import {FlexProps} from '../Flex/Flex.type'; + +export interface TabProps { + label: string; + content: React.ReactNode; +} + +export interface TabsCustomProps { + children: React.ReactElement[]; +} + +export interface TabsStyleProps { + tabsContainerStyle?: FlexProps; +} + +export type TabsProps = TabsCustomProps & TabsStyleProps; diff --git a/HDesign/src/components/Tabs/Tabs.stories.tsx b/HDesign/src/components/Tabs/Tabs.stories.tsx new file mode 100644 index 000000000..a40e60b07 --- /dev/null +++ b/HDesign/src/components/Tabs/Tabs.stories.tsx @@ -0,0 +1,31 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import React from 'react'; + +import Tabs from '@components/Tabs/Tabs'; + +import Tab from './Tab'; + +const meta = { + title: 'Components/Tabs', + component: Tabs, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + args: { + children: [ + ์—†์ง€๋กฑ} />, + ์žˆ์ง€๋กฑ} />, + ], + tabsContainerStyle: { + gap: '0.5rem', + }, + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Tabs/Tabs.style.ts b/HDesign/src/components/Tabs/Tabs.style.ts new file mode 100644 index 000000000..3ea38924c --- /dev/null +++ b/HDesign/src/components/Tabs/Tabs.style.ts @@ -0,0 +1,53 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +export const tabListStyle = (theme: Theme) => + css({ + position: 'relative', + + backgroundColor: theme.colors.white, + + cursor: 'pointer', + + WebkitTapHighlightColor: 'transparent', + + '&::after': { + position: 'absolute', + left: 0, + bottom: 0, + zIndex: 1, + + width: '100%', + height: '0.0625rem', + + backgroundColor: theme.colors.gray, + + content: '""', + }, + }); + +export const tabItemStyle = css({ + flex: 1, + + textAlign: 'center', +}); + +export const tabTextStyle = (theme: Theme, selected: boolean) => + css({ + color: selected ? theme.colors.onTertiary : theme.colors.gray, + }); + +export const indicatorStyle = (theme: Theme, leftPosition: string, tabLength: number) => + css({ + position: 'absolute', + left: leftPosition, + bottom: 0, + zIndex: 2, + + width: `calc(100% / ${tabLength})`, + height: '0.125rem', + + backgroundColor: theme.colors.onSecondary, + transition: 'left 0.3s', + }); diff --git a/HDesign/src/components/Tabs/Tabs.tsx b/HDesign/src/components/Tabs/Tabs.tsx new file mode 100644 index 000000000..0245b5ba7 --- /dev/null +++ b/HDesign/src/components/Tabs/Tabs.tsx @@ -0,0 +1,53 @@ +/** @jsxImportSource @emotion/react */ +import React, {useState} from 'react'; +import {css} from '@emotion/react'; + +import {useTheme} from '@theme/HDesignProvider'; + +import Text from '../Text/Text'; +import Flex from '../Flex/Flex'; + +import {tabListStyle, indicatorStyle, tabItemStyle, tabTextStyle} from './Tabs.style'; +import {TabsProps} from './Tab.type'; + +const Tabs: React.FC = ({children, tabsContainerStyle}) => { + const {theme} = useTheme(); + const [activeTabIndex, setActiveTabIndex] = useState(0); + + const isActive = (index: number) => activeTabIndex === index; + const tabItemCount = children.length; + + return ( + +
    + + {children.map((tabItem, index) => ( + + ))} +
    + +
+
+ {children[activeTabIndex].props.content} +
+
+ ); +}; + +export default Tabs; diff --git a/HDesign/src/components/Text/Text.stories.tsx b/HDesign/src/components/Text/Text.stories.tsx new file mode 100644 index 000000000..5e5ec2287 --- /dev/null +++ b/HDesign/src/components/Text/Text.stories.tsx @@ -0,0 +1,40 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import Text from '@components/Text/Text'; + +const meta = { + title: 'Components/Text', + component: Text, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + size: { + description: '', + control: {type: 'select'}, + options: [ + 'head', + 'title', + 'subTitle', + 'bodyBold', + 'body', + 'smallBodyBold', + 'smallBody', + 'caption', + 'captionBold', + 'tiny', + ], + }, + }, + args: { + size: 'body', + children: 'text', + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Text/Text.style.ts b/HDesign/src/components/Text/Text.style.ts new file mode 100644 index 000000000..650260e62 --- /dev/null +++ b/HDesign/src/components/Text/Text.style.ts @@ -0,0 +1,29 @@ +import type {TextStylePropsWithTheme} from './Text.type'; + +import {css} from '@emotion/react'; + +// TODO: (@todari) themeProvider ์ด์šฉํ•˜๋„๋ก ๋ณ€๊ฒฝ +import TYPOGRAPHY from '@token/typography'; + +export const getSizeStyling = ({size, textColor, theme}: Required) => { + const style = { + head: css(TYPOGRAPHY.head), + title: css(TYPOGRAPHY.title), + subTitle: css(TYPOGRAPHY.subTitle), + bodyBold: css(TYPOGRAPHY.bodyBold), + body: css(TYPOGRAPHY.body), + smallBodyBold: css(TYPOGRAPHY.smallBodyBold), + smallBody: css(TYPOGRAPHY.smallBody), + captionBold: css(TYPOGRAPHY.captionBold), + caption: css(TYPOGRAPHY.caption), + tiny: css(TYPOGRAPHY.tiny), + }; + + const colorStyle = css({color: theme.colors[textColor]}); + + const baseStyle = css({ + whiteSpace: 'pre-line', + }); + + return [style[size], colorStyle, baseStyle]; +}; diff --git a/HDesign/src/components/Text/Text.tsx b/HDesign/src/components/Text/Text.tsx new file mode 100644 index 000000000..9b7853aa8 --- /dev/null +++ b/HDesign/src/components/Text/Text.tsx @@ -0,0 +1,19 @@ +/** @jsxImportSource @emotion/react */ +import type {TextProps} from '@components/Text/Text.type'; + +import React from 'react'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {getSizeStyling} from './Text.style'; + +const Text: React.FC = ({size = 'body', textColor = 'black', children, ...attributes}: TextProps) => { + const {theme} = useTheme(); + return ( +

+ {children} +

+ ); +}; + +export default Text; diff --git a/HDesign/src/components/Text/Text.type.ts b/HDesign/src/components/Text/Text.type.ts new file mode 100644 index 000000000..157591abf --- /dev/null +++ b/HDesign/src/components/Text/Text.type.ts @@ -0,0 +1,30 @@ +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +export type TextSize = + | 'head' + | 'title' + | 'subTitle' + | 'body' + | 'smallBody' + | 'caption' + | 'tiny' + | 'bodyBold' + | 'smallBodyBold' + | 'captionBold'; + +export interface TextStyleProps { + size?: TextSize; + textColor?: ColorKeys; +} + +export interface TextStylePropsWithTheme extends TextStyleProps { + theme: Theme; +} + +export interface TextCustomProps {} + +export type TextOptionProps = TextStyleProps & TextCustomProps; + +export type TextProps = React.ComponentProps<'p'> & TextOptionProps; diff --git a/HDesign/src/components/TextButton/TextButton.stories.tsx b/HDesign/src/components/TextButton/TextButton.stories.tsx new file mode 100644 index 000000000..9873df3f4 --- /dev/null +++ b/HDesign/src/components/TextButton/TextButton.stories.tsx @@ -0,0 +1,50 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import TextButton from '@components/TextButton/TextButton'; + +const meta = { + title: 'Components/TextButton', + component: TextButton, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + textSize: { + description: '', + control: {type: 'select'}, + options: [ + 'head', + 'title', + 'subTitle', + 'bodyBold', + 'body', + 'smallBodyBold', + 'smallBody', + 'caption', + 'captionBold', + 'tiny', + ], + }, + textColor: { + description: '', + control: {type: 'select'}, + options: ['black', 'gray'], + }, + children: { + description: '', + control: {type: 'text'}, + }, + }, + args: { + textColor: 'black', + textSize: 'bodyBold', + children: '๋’ค๋กœ๊ฐ€๊ธฐ', + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/TextButton/TextButton.style.ts b/HDesign/src/components/TextButton/TextButton.style.ts new file mode 100644 index 000000000..c8d8738fe --- /dev/null +++ b/HDesign/src/components/TextButton/TextButton.style.ts @@ -0,0 +1,10 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +interface TextButtonStyleProps { + textColor: ColorKeys; + theme: Theme; +} diff --git a/HDesign/src/components/TextButton/TextButton.tsx b/HDesign/src/components/TextButton/TextButton.tsx new file mode 100644 index 000000000..9e73667d5 --- /dev/null +++ b/HDesign/src/components/TextButton/TextButton.tsx @@ -0,0 +1,25 @@ +/** @jsxImportSource @emotion/react */ +import {forwardRef} from 'react'; + +import {useTheme} from '@theme/HDesignProvider'; + +import Text from '../Text/Text'; + +import {TextButtonProps} from './TextButton.type'; + +export const TextButton: React.FC = forwardRef(function Button( + {textColor, textSize, children, ...htmlProps}: TextButtonProps, + ref, +) { + const {theme} = useTheme(); + + return ( + + ); +}); + +export default TextButton; diff --git a/HDesign/src/components/TextButton/TextButton.type.ts b/HDesign/src/components/TextButton/TextButton.type.ts new file mode 100644 index 000000000..0299d89b9 --- /dev/null +++ b/HDesign/src/components/TextButton/TextButton.type.ts @@ -0,0 +1,15 @@ +import {TextSize} from '../Text/Text.type'; + +export type TextColor = 'black' | 'gray'; + +export interface TextButtonStyleProps { + textColor: TextColor; +} + +export interface TextButtonCustomProps { + textSize: TextSize; +} + +export type TextButtonOptionProps = TextButtonStyleProps & TextButtonCustomProps; + +export type TextButtonProps = React.ComponentProps<'button'> & TextButtonOptionProps; diff --git a/HDesign/src/components/Title/Title.stories.tsx b/HDesign/src/components/Title/Title.stories.tsx new file mode 100644 index 000000000..2c91287b4 --- /dev/null +++ b/HDesign/src/components/Title/Title.stories.tsx @@ -0,0 +1,38 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import Title from '@components/Title/Title'; + +const meta = { + title: 'Components/Title', + component: Title, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + title: { + description: '', + control: {type: 'text'}, + }, + description: { + description: '', + control: {type: 'text'}, + }, + price: { + description: '', + control: {type: 'number'}, + }, + }, + args: { + title: 'ํŽ˜์ด์ง€ ์ œ๋ชฉ์ด์—์š”', + description: `์ด๊ณณ์—๋Š” ํŽ˜์ด์ง€ ์„ค๋ช…์ด ๋“ค์–ด๊ฐ€์š”. + ํŽ˜์ด์ง€์— ๋Œ€ํ•œ ์„ค๋ช…์„ ์ž์„ธํ•˜๊ฒŒ ์ ์–ด์ฃผ๋ฉด ์ข‹์•„์š” :)`, + price: 100000, + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Title/Title.style.ts b/HDesign/src/components/Title/Title.style.ts new file mode 100644 index 000000000..ab347a214 --- /dev/null +++ b/HDesign/src/components/Title/Title.style.ts @@ -0,0 +1,19 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +export const titleContainerStyle = (theme: Theme) => + css({ + display: 'flex', + flexDirection: 'column', + width: '100%', + gap: '0.5rem', + backgroundColor: theme.colors.white, + padding: '1rem', + }); + +export const priceContainerStyle = css({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'end', +}); diff --git a/HDesign/src/components/Title/Title.tsx b/HDesign/src/components/Title/Title.tsx new file mode 100644 index 000000000..e17de5e88 --- /dev/null +++ b/HDesign/src/components/Title/Title.tsx @@ -0,0 +1,34 @@ +/** @jsxImportSource @emotion/react */ +import Flex from '@components/Flex/Flex'; +import Text from '@components/Text/Text'; +import {priceContainerStyle, titleContainerStyle} from '@components/Title/Title.style'; +import {TitleProps} from '@components/Title/Title.type'; + +import {useTheme} from '@theme/HDesignProvider'; + +export const Title: React.FC = ({title, description, price}: TitleProps) => { + const {theme} = useTheme(); + return ( +
+ {title} + {description && ( + + {description} + + )} + {price !== undefined && ( +
+ + ์ „์ฒด ์ง€์ถœ ๊ธˆ์•ก + + + {price.toLocaleString('ko-kr')} + ์› + +
+ )} +
+ ); +}; + +export default Title; diff --git a/HDesign/src/components/Title/Title.type.ts b/HDesign/src/components/Title/Title.type.ts new file mode 100644 index 000000000..4b12f23b2 --- /dev/null +++ b/HDesign/src/components/Title/Title.type.ts @@ -0,0 +1,11 @@ +export interface TitleStyleProps {} + +export interface TitleCustomProps { + title: string; + description?: string; + price?: number; +} + +export type TitleOptionProps = TitleStyleProps & TitleCustomProps; + +export type TitleProps = React.ComponentProps<'div'> & TitleOptionProps; diff --git a/HDesign/src/components/Toast/Toast.stories.tsx b/HDesign/src/components/Toast/Toast.stories.tsx new file mode 100644 index 000000000..fd672959c --- /dev/null +++ b/HDesign/src/components/Toast/Toast.stories.tsx @@ -0,0 +1,71 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import Toast from '@components/Toast/Toast'; + +const meta = { + title: 'Components/Toast', + component: Toast, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + args: { + type: 'confirm', + position: 'top', + top: '80px', + message: `์„œ๋ฒ„ ์˜ค๋ฅ˜๋กœ ์ธํ•ด ์ธ์›์„ ์„ค์ •ํ•˜๋Š”๋ฐ ์‹คํŒจํ–ˆ์–ด์š”. +๋‘๊ธ€์ž๋ฉด ์ด๋ ‡๊ฒŒ ๋ณด์—ฌ์š”.`, + onUndo: () => alert('๋˜๋Œ๋ฆฌ๊ธฐ ๋ฒ„ํŠผ์ด ๋ˆŒ๋ ธ์Šต๋‹ˆ๋‹ค. ์‹คํ–‰ํ•  ๋กœ์ง์„ ์ „๋‹ฌํ•ด์ฃผ์„ธ์š”'), + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const ConfirmToast: Story = { + args: { + ...meta.args, + type: 'confirm', + top: '80px', + message: `์ด ์ฒซ๋ฒˆ์งธ ํ† ์ŠคํŠธ ๊ทธ๋ฆผ์ž ์ง™์€๊ฑฐ ๋‘ ๊ฐœ ๋– ์„œ ๊ทธ๋Ÿฐ๊ฑฐ์ž„ css ์ž˜๋ชปํ•œ๊ฑฐ ์•„๋‹™๋‹ˆ๋‹ค. ์ž˜๋ชป ์—†์Šต๋‹ˆ๋‹ค. ์Šคํ† ๋ฆฌ๋ถ์ด ์ž˜๋ชปํ•œ๊ฑฐ์—์š”. ์ €ํฌ๋Š” ์ตœ์„ ์„ ๋‹คํ–ˆ์–ด์š”.. `, + }, +}; + +export const ConfirmToastWithoutUndo: Story = { + args: { + ...meta.args, + onUndo: undefined, + top: '160px', + }, +}; + +export const ErrorToast: Story = { + args: { + ...meta.args, + top: '240px', + type: 'error', + message: `๋‹˜ ์ด๊ฑฐ ๋‹ค ์ž‘์„ฑํ–ˆ๋Š”๋ฐ, ํ˜น์‹œ ๋˜๋Œ๋ฆผ? + ๋˜๋Œ๋ฆด ์ˆ˜๋„ ์žˆ์Œ ใ…‡ใ…‡ ๊ตฟ`, + }, +}; + +export const ErrorToastWithoutUndo: Story = { + args: { + ...meta.args, + top: '320px', + onUndo: undefined, + type: 'error', + }, +}; + +export const NoneToast: Story = { + args: { + ...meta.args, + top: '400px', + onUndo: undefined, + type: 'none', + message: '์›จ๋””๋Š” ์ปค๋น„์˜ ๋จน์ž‡๊ฐ์ธ๊ฐ€์š”? ๊ทธ์น˜๋งŒ ๊ฐ์ž๋Š” ์›จ๋””ํ•œํ…Œ ๋จนํž˜ ์ฟ ์Šค์ฟ ์Šค ใ…‹', + }, +}; diff --git a/HDesign/src/components/Toast/Toast.style.ts b/HDesign/src/components/Toast/Toast.style.ts new file mode 100644 index 000000000..0496bc722 --- /dev/null +++ b/HDesign/src/components/Toast/Toast.style.ts @@ -0,0 +1,44 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +import {ToastPosition} from './Toast.type'; + +type ToastMarginStyle = { + position?: ToastPosition; + bottom?: string; + top?: string; +}; + +export const toastMarginStyle = ({position, bottom, top}: ToastMarginStyle) => + css({ + position: 'absolute', + bottom: position === 'bottom' ? `${bottom}` : 'auto', + top: position === 'top' ? `${top}` : 'auto', + left: '50%', + transform: 'translate(-50%)', + + width: '100%', + maxWidth: '48rem', + paddingInline: '0.5rem', + }); + +export const toastStyle = (theme: Theme) => + css({ + width: '100%', + padding: '0.625rem 1rem', + + backgroundColor: theme.colors.gray, + boxShadow: '0 8px 12px rgba(0, 0, 0, 0.16);', + + borderRadius: '1.25rem', + }); + +export const textStyle = (theme: Theme) => + css({ + width: '100%', + + color: theme.colors.white, + + whiteSpace: 'pre-line', + }); diff --git a/HDesign/src/components/Toast/Toast.tsx b/HDesign/src/components/Toast/Toast.tsx new file mode 100644 index 000000000..972ce6220 --- /dev/null +++ b/HDesign/src/components/Toast/Toast.tsx @@ -0,0 +1,73 @@ +/** @jsxImportSource @emotion/react */ +import {createPortal} from 'react-dom'; + +import Text from '@components/Text/Text'; +import Flex from '@components/Flex/Flex'; +import Icon from '@components/Icon/Icon'; + +import {useTheme} from '@theme/HDesignProvider'; + +import Button from '../Button/Button'; + +import {toastStyle, textStyle, toastMarginStyle} from './Toast.style'; +import {ToastProps, ToastType} from './Toast.type'; + +const renderIcon = (type: ToastType) => { + switch (type) { + case 'error': + return ; + + case 'confirm': + return ; + + case 'none': + return null; + + default: + return null; + } +}; + +const Toast = ({ + type = 'confirm', + top = '0px', + bottom = '0px', + isClickToClose = true, + position = 'bottom', + message, + onUndo, + onClose, + ...htmlProps +}: ToastProps) => { + const {theme} = useTheme(); + const styleProps = {position, top, bottom}; + + const handleClickToClose = () => { + if (!isClickToClose || !onClose) return; + + onClose(); + }; + + return createPortal( +
+
+ + + {renderIcon(type)} + + {message} + + + {onUndo && ( + + )} + +
+
, + document.body, + ); +}; + +export default Toast; diff --git a/HDesign/src/components/Toast/Toast.type.ts b/HDesign/src/components/Toast/Toast.type.ts new file mode 100644 index 000000000..12a436c2d --- /dev/null +++ b/HDesign/src/components/Toast/Toast.type.ts @@ -0,0 +1,21 @@ +export type ToastPosition = 'bottom' | 'top'; +export type ToastType = 'error' | 'confirm' | 'none'; + +export interface ToastStyleProps { + bottom?: string; + top?: string; +} + +export interface ToastOptionProps { + position?: ToastPosition; + type?: ToastType; + onUndo?: () => void; + isClickToClose?: boolean; + onClose?: () => void; +} + +export interface ToastRequiredProps { + message: string; +} + +export type ToastProps = React.ComponentProps<'div'> & ToastStyleProps & ToastOptionProps & ToastRequiredProps; diff --git a/HDesign/src/components/Toast/ToastProvider.stories.tsx b/HDesign/src/components/Toast/ToastProvider.stories.tsx new file mode 100644 index 000000000..32c8c6917 --- /dev/null +++ b/HDesign/src/components/Toast/ToastProvider.stories.tsx @@ -0,0 +1,46 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import Button from '../Button/Button'; + +import {ToastProvider, useToast} from './ToastProvider'; + +const meta = { + title: 'Components/ToastProvider', + component: ToastProvider, + tags: ['autodocs'], + decorators: [ + Story => ( + + + + ), + ], +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = { + decorators: [ + () => { + const {showToast} = useToast(); + + return ( + + ); + }, + ], +}; diff --git a/HDesign/src/components/Toast/ToastProvider.tsx b/HDesign/src/components/Toast/ToastProvider.tsx new file mode 100644 index 000000000..9201fdc6d --- /dev/null +++ b/HDesign/src/components/Toast/ToastProvider.tsx @@ -0,0 +1,59 @@ +/** @jsxImportSource @emotion/react */ +import {createContext, useCallback, useContext, useEffect, useState} from 'react'; + +import {ToastProps} from './Toast.type'; +import Toast from './Toast'; + +export const ToastContext = createContext(null); + +interface ToastContextProps { + showToast: (args: ShowToast) => void; +} + +type ShowToast = ToastProps & { + showingTime?: number; + isAlwaysOn?: boolean; +}; + +const ToastProvider = ({children}: React.PropsWithChildren) => { + const [currentToast, setCurrentToast] = useState(null); + + const showToast = useCallback(({showingTime = 3000, isAlwaysOn = false, ...toastProps}: ShowToast) => { + setCurrentToast({showingTime, isAlwaysOn, ...toastProps}); + }, []); + + const closeToast = () => { + setCurrentToast(null); + }; + + useEffect(() => { + if (!currentToast) return; + + if (!currentToast.isAlwaysOn) { + const timer = setTimeout(() => { + setCurrentToast(null); + }, currentToast.showingTime); + + return () => clearTimeout(timer); + } + }, [currentToast]); + + return ( + + {currentToast && } + {children} + + ); +}; + +const useToast = () => { + const context = useContext(ToastContext); + + if (!context) { + throw new Error('useToast๋Š” ToastProvider ๋‚ด์—์„œ ์‚ฌ์šฉ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); + } + + return context; +}; + +export {ToastProvider, useToast}; diff --git a/HDesign/src/components/TopNav/Back.tsx b/HDesign/src/components/TopNav/Back.tsx new file mode 100644 index 000000000..cfb55e24d --- /dev/null +++ b/HDesign/src/components/TopNav/Back.tsx @@ -0,0 +1,17 @@ +/** @jsxImportSource @emotion/react */ +import React from 'react'; +import {useNavigate} from 'react-router-dom'; + +import TextButton from '@components/TextButton/TextButton'; + +function Back() { + const navigate = useNavigate(); + + return ( + navigate(-1)} textSize="bodyBold" textColor="gray"> + ๋’ค๋กœ๊ฐ€๊ธฐ + + ); +} + +export default Back; diff --git a/HDesign/src/components/TopNav/TopNav.stories.tsx b/HDesign/src/components/TopNav/TopNav.stories.tsx new file mode 100644 index 000000000..0c96161a5 --- /dev/null +++ b/HDesign/src/components/TopNav/TopNav.stories.tsx @@ -0,0 +1,50 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import React from 'react'; +import {reactRouterParameters, withRouter} from 'storybook-addon-react-router-v6'; + +import TopNav from '@components/TopNav/TopNav'; + +import Switch from '../Switch/Switch'; + +import Back from './Back'; + +const meta = { + title: 'Components/TopNav', + component: TopNav, + tags: ['autodocs'], + decorators: [withRouter], + parameters: { + reactRouter: reactRouterParameters({ + location: { + pathParams: { + eventId: '123123', + }, + }, + routing: {path: '/event/:eventId/home'}, + }), + // layout: 'centered', + }, + argTypes: { + children: { + description: '', + control: {type: 'select'}, + options: ['Back', 'Switch', 'Any'], + mapping: { + Back: , + Switch: console.log(value)} />, + Any:
, + }, + }, + }, + args: { + children: 'Back', + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/TopNav/TopNav.style.ts b/HDesign/src/components/TopNav/TopNav.style.ts new file mode 100644 index 000000000..9ca69c7b0 --- /dev/null +++ b/HDesign/src/components/TopNav/TopNav.style.ts @@ -0,0 +1,18 @@ +import {css} from '@emotion/react'; + +export const topNavStyle = css({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + padding: '0 1rem', + width: '100%', +}); + +export const topNavNonStyle = css({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + padding: '0 1rem', + width: '100%', + height: '1.5rem', +}); diff --git a/HDesign/src/components/TopNav/TopNav.tsx b/HDesign/src/components/TopNav/TopNav.tsx new file mode 100644 index 000000000..643cd5e3b --- /dev/null +++ b/HDesign/src/components/TopNav/TopNav.tsx @@ -0,0 +1,20 @@ +/** @jsxImportSource @emotion/react */ +import React from 'react'; + +import Switch from '@components/Switch/Switch'; + +import {topNavNonStyle, topNavStyle} from './TopNav.style'; +import Back from './Back'; + +const TopNav: React.FC = ({children}) => { + const hasBack = React.Children.toArray(children).some(child => React.isValidElement(child) && child.type === Back); + const hasSwitch = React.Children.toArray(children).some( + child => React.isValidElement(child) && child.type === Switch, + ); + + const isExistNav = hasBack || hasSwitch; + + return
{children}
; +}; + +export default TopNav; diff --git a/HDesign/src/index.tsx b/HDesign/src/index.tsx new file mode 100644 index 000000000..656690951 --- /dev/null +++ b/HDesign/src/index.tsx @@ -0,0 +1,62 @@ +import BottomSheet from '@components/BottomSheet/BottomSheet'; +import Button from '@components/Button/Button'; +import DragHandleItem from '@components/DragHandleItem/DragHandleItem'; +import DragHandleItemContainer from '@components/DragHandleItemContainer/DragHandleItemContainer'; +import EditableItem from '@components/EditableItem/EditableItem'; +import ExpenseList from '@components/ExpenseList/ExpenseList'; +import FixedButton from '@components/FixedButton/FixedButton'; +import Flex from '@components/Flex/Flex'; +import Icon from '@components/Icon/Icon'; +import IconButton from '@components/IconButton/IconButton'; +import Input from '@components/Input/Input'; +import LabelInput from '@components/LabelInput/LabelInput'; +import ListButton from '@components/ListButton/ListButton'; +import LabelGroupInput from '@components/LabelGroupInput/LabelGroupInput'; +import Search from '@components/Search/Search'; +import Switch from '@components/Switch/Switch'; +import Tab from '@components/Tabs/Tab'; +import Tabs from '@components/Tabs/Tabs'; +import Text from '@components/Text/Text'; +import TextButton from '@components/TextButton/TextButton'; +import Title from '@components/Title/Title'; +import Toast from '@components/Toast/Toast'; +import Back from '@components/TopNav/Back'; +import TopNav from '@components/TopNav/TopNav'; +import {ToastProvider, useToast} from '@components/Toast/ToastProvider'; + +import {MainLayout} from '@layouts/MainLayout'; +import {ContentLayout} from '@layouts/ContentLayout'; + +import {HDesignProvider} from '@theme/HDesignProvider'; + +export { + BottomSheet, + Button, + DragHandleItem, + DragHandleItemContainer, + EditableItem, + ExpenseList, + FixedButton, + Flex, + Icon, + IconButton, + Input, + LabelInput, + ListButton, + LabelGroupInput, + Search, + Switch, + Tab, + Tabs, + Text, + TextButton, + Title, + Toast, + TopNav, + Back, + MainLayout, + ContentLayout, + ToastProvider, + useToast, + HDesignProvider, +}; diff --git a/HDesign/src/layouts/ContentLayout.tsx b/HDesign/src/layouts/ContentLayout.tsx new file mode 100644 index 000000000..757a580ec --- /dev/null +++ b/HDesign/src/layouts/ContentLayout.tsx @@ -0,0 +1,25 @@ +import {PropsWithChildren} from 'react'; + +import {Flex} from '..'; + +type ContentLayoutBackground = 'white' | 'gray'; + +interface ContentLayoutProps extends PropsWithChildren { + backgroundColor?: ContentLayoutBackground; +} + +export function ContentLayout({backgroundColor, children}: ContentLayoutProps) { + return ( + + {children} + + ); +} diff --git a/HDesign/src/layouts/MainLayout.tsx b/HDesign/src/layouts/MainLayout.tsx new file mode 100644 index 000000000..22012fde8 --- /dev/null +++ b/HDesign/src/layouts/MainLayout.tsx @@ -0,0 +1,26 @@ +import {PropsWithChildren} from 'react'; + +import {Flex} from '..'; + +type MainLayoutBackground = 'white' | 'gray' | 'lightGray'; + +interface MainLayoutProps extends PropsWithChildren { + backgroundColor?: MainLayoutBackground; +} + +export function MainLayout({backgroundColor, children}: MainLayoutProps) { + return ( + + {children} + + ); +} diff --git a/HDesign/src/theme/GlobalStyle.ts b/HDesign/src/theme/GlobalStyle.ts new file mode 100644 index 000000000..f1b7b699b --- /dev/null +++ b/HDesign/src/theme/GlobalStyle.ts @@ -0,0 +1,123 @@ +import {css} from '@emotion/react'; + +export const GlobalStyle = css` + *:where(:not(html, iframe, canvas, img, svg, video, audio):not(svg *, symbol *)) { + all: unset; + display: revert; + } + + /* Preferred box-sizing value */ + *, + *::before, + *::after { + box-sizing: border-box; + } + + /* Fix mobile Safari increase font-size on landscape mode */ + html { + -moz-text-size-adjust: none; + -webkit-text-size-adjust: none; + text-size-adjust: none; + } + + /* Reapply the pointer cursor for anchor tags */ + a, + button { + cursor: revert; + line-height: 0; + } + + button:disabled { + cursor: default; + } + + /* Remove list styles (bullets/numbers) */ + ol, + ul, + menu, + summary { + list-style: none; + } + + /* Removes spacing between cells in tables */ + table { + border-collapse: collapse; + } + + /* Safari - solving issue when using user-select:none on the text input doesn't working */ + input, + textarea { + -webkit-user-select: auto; + } + + /* Revert the 'white-space' property for textarea elements on Safari */ + textarea { + white-space: revert; + } + + /* Minimum style to allow to style meter element */ + meter { + -webkit-appearance: revert; + appearance: revert; + } + + /* Preformatted text - use only for this feature */ + :where(pre) { + all: revert; + box-sizing: border-box; + } + + /* Fix the feature of 'hidden' attribute. + display: revert; revert to element instead of attribute */ + :where([hidden]) { + display: none; + } + + /* Revert for bug in Chromium browsers + - Fix for the content editable attribute will work properly. + - webkit-user-select: auto; added for Safari in case of using user-select:none on wrapper element */ + :where([contenteditable]:not([contenteditable='false'])) { + -moz-user-modify: read-write; + -webkit-user-modify: read-write; + overflow-wrap: break-word; + -webkit-line-break: after-white-space; + -webkit-user-select: auto; + } + + /* Apply back the draggable feature - exist only in Chromium and Safari */ + :where([draggable='true']) { + -webkit-user-drag: element; + } + + /* Revert Modal native behavior */ + :where(dialog:modal) { + all: revert; + box-sizing: border-box; + } + + /* Remove details summary webkit styles */ + ::-webkit-details-marker { + display: none; + } + + /* Chrome, Safari, Edge, Opera */ + input::-webkit-outer-spin-button, + input::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; + } + + /* Firefox */ + input[type='number'] { + -moz-appearance: textfield; + } + + #root { + display: flex; + justify-content: center; + } + + button { + cursor: pointer; + } +`; diff --git a/HDesign/src/theme/HDesignProvider.tsx b/HDesign/src/theme/HDesignProvider.tsx new file mode 100644 index 000000000..6c7c571a3 --- /dev/null +++ b/HDesign/src/theme/HDesignProvider.tsx @@ -0,0 +1,37 @@ +import React, {createContext, useContext, useState, ReactNode} from 'react'; +import {Global} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; +import {GlobalStyle} from '@theme/GlobalStyle'; + +import {COLORS} from '@token/colors'; +import {TYPOGRAPHY} from '@token/typography'; + +interface ThemeContextProps { + theme: Theme; +} + +const defaultTheme: Theme = { + colors: COLORS, + typography: TYPOGRAPHY, +}; + +const ThemeContext = createContext(undefined); + +export const HDesignProvider: React.FC<{children: ReactNode}> = ({children}) => { + const [theme, _] = useState(defaultTheme); + return ( + + + {children} + + ); +}; + +export const useTheme = (): ThemeContextProps => { + const context = useContext(ThemeContext); + if (!context) { + throw new Error('useTheme must be used within a HDesignProvider'); + } + return context; +}; diff --git a/HDesign/src/theme/theme.type.ts b/HDesign/src/theme/theme.type.ts new file mode 100644 index 000000000..dffd961f0 --- /dev/null +++ b/HDesign/src/theme/theme.type.ts @@ -0,0 +1,7 @@ +import {ColorTokens} from '@token/colors'; +import {TypographyTokens} from '@token/typography'; + +export interface Theme { + colors: ColorTokens; + typography: TypographyTokens; +} diff --git a/HDesign/src/token/colors.ts b/HDesign/src/token/colors.ts new file mode 100644 index 000000000..3dccdf2d3 --- /dev/null +++ b/HDesign/src/token/colors.ts @@ -0,0 +1,109 @@ +const PRIMITIVE_COLORS = { + white: '#FFFFFF', + purple: { + 50: '#f4e8ff', + 100: '#e0c7fe', + 200: '#cba0fe', + 300: '#b575ff', + 400: '#a350fd', + 500: '#8f2bf3', + 600: '#8425ec', + 700: '#7519e3', + 800: '#6712db', + 900: '#5100cd', + }, + pink: { + 50: '#ffe1ff', + 100: '#feafd9', + 200: '#ff75bf', + 300: '#fc28a1', + 400: '#f60087', + 500: '#f2006d', + 600: '#e1006a', + 700: '#ca0065', + 800: '#b30062', + 900: '#8b005b', + }, + yellow: { + 50: '#fdffe9', + 100: '#f7fdc5', + 200: '#f0fb9d', + 300: '#e8f972', + 400: '#ecff59', + 500: '#e5fb31', + 600: '#daeb2e', + 700: '#c9d323', + 800: '#b9bb17', + 900: '#9e9305', + }, + green: { + 50: '#f4ffe8', + 100: '#e4ffc6', + 200: '#d1ff9f', + 300: '#bfff75', + 400: '#b0fd51', + 500: '#a4f932', + 600: '#9de728', + 700: '#90cf18', + 800: '#85b704', + 900: '#748f00', + }, + gray: { + 50: '#F9F8FD', + 100: '#F1F0F5', + 200: '#E7E6EB', + 300: '#D6D5DA', + 400: '#B2B1B6', + 500: '#929195', + 600: '#6A696D', + 700: '#56555A', + 800: '#38373B', + 900: '#18171B', + }, +}; + +type Color = string; + +export type ColorKeys = + | 'white' + | 'black' + | 'primary' + | 'onPrimary' + | 'secondary' + | 'onSecondary' + | 'tertiary' + | 'onTertiary' + | 'gray' + | 'darkGray' + | 'grayContainer' + | 'lightGrayContainer' + | 'error' + | 'errorContainer' + | 'onErrorContainer' + | 'warn' + | 'complete'; +export type ColorTokens = Record; + +// TODO: (@soha) ๋Œ€๊ด„ํ˜ธ ์‚ฌ์šฉ์— ๋Œ€ํ•ด ๋…ผ์˜ +export const COLORS: ColorTokens = { + white: PRIMITIVE_COLORS.white, + black: PRIMITIVE_COLORS.gray[700], + + primary: PRIMITIVE_COLORS.purple[300], + onPrimary: PRIMITIVE_COLORS.white, + secondary: PRIMITIVE_COLORS.purple[50], + onSecondary: PRIMITIVE_COLORS.purple[600], + tertiary: PRIMITIVE_COLORS.gray[200], + onTertiary: PRIMITIVE_COLORS.gray[700], + + gray: PRIMITIVE_COLORS.gray[400], + darkGray: PRIMITIVE_COLORS.gray[500], + grayContainer: PRIMITIVE_COLORS.gray[100], + lightGrayContainer: PRIMITIVE_COLORS.gray[50], + + error: PRIMITIVE_COLORS.pink[200], + errorContainer: PRIMITIVE_COLORS.pink[50], + onErrorContainer: PRIMITIVE_COLORS.pink[300], + warn: PRIMITIVE_COLORS.yellow[400], + complete: PRIMITIVE_COLORS.green[300], +}; diff --git a/HDesign/src/token/typography.ts b/HDesign/src/token/typography.ts new file mode 100644 index 000000000..c88d61ea9 --- /dev/null +++ b/HDesign/src/token/typography.ts @@ -0,0 +1,67 @@ +type Typography = Record; +export type TypographyTokens = Record; + +export const TYPOGRAPHY: TypographyTokens = { + head: { + fontFamily: 'Pretendard', + fontSize: '3rem', + lineHeight: '1.5', + fontWeight: '700', + }, + title: { + fontFamily: 'Pretendard', + fontSize: '2rem', + lineHeight: '1.5', + fontWeight: '700', + }, + subTitle: { + fontFamily: 'Pretendard', + fontSize: '1.5rem', + lineHeight: '1.5', + fontWeight: '700', + }, + bodyBold: { + fontFamily: 'Pretendard', + fontSize: '1rem', + lineHeight: '1.5', + fontWeight: '700', + }, + body: { + fontFamily: 'Pretendard', + fontSize: '1rem', + lineHeight: '1.5', + fontWeight: '400', + }, + smallBodyBold: { + fontFamily: 'Pretendard', + fontSize: '0.875rem', + lineHeight: '1.5', + fontWeight: '700', + }, + smallBody: { + fontFamily: 'Pretendard', + fontSize: '0.875rem', + lineHeight: '1.5', + fontWeight: '400', + }, + captionBold: { + fontFamily: 'Pretendard', + fontSize: '0.75rem', + lineHeight: '1.5', + fontWeight: '700', + }, + caption: { + fontFamily: 'Pretendard', + fontSize: '0.75rem', + lineHeight: '1.5', + fontWeight: '400', + }, + tiny: { + fontFamily: 'Pretendard', + fontSize: '0.625rem', + lineHeight: '1.5', + fontWeight: '400', + }, +}; + +export default TYPOGRAPHY; diff --git a/HDesign/src/type/strictPropsWithChildren.ts b/HDesign/src/type/strictPropsWithChildren.ts new file mode 100644 index 000000000..684fbcc76 --- /dev/null +++ b/HDesign/src/type/strictPropsWithChildren.ts @@ -0,0 +1,3 @@ +export type StrictPropsWithChildren

= P & { + children: React.ReactNode; +}; diff --git a/HDesign/src/type/withTheme.ts b/HDesign/src/type/withTheme.ts new file mode 100644 index 000000000..bae8dc318 --- /dev/null +++ b/HDesign/src/type/withTheme.ts @@ -0,0 +1,5 @@ +import {Theme} from '@theme/theme.type'; + +export type WithTheme

= P & { + theme: Theme; +}; diff --git a/HDesign/src/utils/changeCamelCaseToKebabCase.ts b/HDesign/src/utils/changeCamelCaseToKebabCase.ts new file mode 100644 index 000000000..2bca7c1b7 --- /dev/null +++ b/HDesign/src/utils/changeCamelCaseToKebabCase.ts @@ -0,0 +1,3 @@ +export const changeCamelCaseToKebabCase = (str: string) => { + return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); +}; diff --git a/HDesign/src/utils/colors.ts b/HDesign/src/utils/colors.ts new file mode 100644 index 000000000..116c670b0 --- /dev/null +++ b/HDesign/src/utils/colors.ts @@ -0,0 +1,88 @@ +export const hexToRgb = (hex: string) => { + hex = hex.slice(1); + if (hex.length === 3) { + hex = hex + .split('') + .reduce((acc, a) => { + acc.push(a + a); + return acc; + }, []) + .join(''); + } + + if (hex.length !== 6) { + throw new Error(`์ž˜๋ชป๋œ ์ƒ‰์ƒ๊ฐ’์ด ์ž…๋ ฅ๋์Šต๋‹ˆ๋‹ค. : ${hex} 3์ž๋ฆฌ(#fff), 6์ž๋ฆฌ(#fe0000)hex ๊ฐ’๋งŒ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.`); + } + + const regex = new RegExp(`.{1,2}`, 'g'); + const hexArray = hex.match(regex) as string[]; + + return `rgb(${hexArray.map(n => parseInt(n, 16)).join(', ')})`; +}; + +export const rgbToColors = (rgb: string) => { + if (rgb.slice(0, 3) !== 'rgb') { + throw new Error('์ž˜๋ชป๋œ ์ƒ‰์ƒ๊ฐ’์ด ์ž…๋ ฅ๋์Šต๋‹ˆ๋‹ค. rgb() ๊ฐ’๋งŒ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.'); + } + + return rgb + .slice(4, -1) + .split(',') + .map(a => Number(a.trim())); +}; + +export const hexToColors = (hex: string) => { + return rgbToColors(hexToRgb(hex)); +}; + +function intToHex(int: number) { + const hex = int.toString(16); + return hex.length === 1 ? `0${hex}` : hex; +} + +export const colorsToRgb = (colors: number[]) => { + return `rgb(${colors.join(', ')})`; +}; + +export const rgbToHex = (rgb: string) => { + const colors = rgbToColors(rgb); + return `#${colors.map((n, i) => intToHex(i === 3 ? Math.round(255 * n) : n)).join('')}`; +}; + +export const colorsToHex = (colors: number[]) => { + return rgbToHex(colorsToRgb(colors)); +}; + +export const setDarker = (hex: string, coefficient: number) => { + const colors = hexToColors(hex); + const adjustCoefficient = coefficient > 1 ? 1 : coefficient < 0 ? 0 : coefficient; + const darkerColors = colors.map(color => Math.round(color * (1 - adjustCoefficient))); + + return colorsToHex(darkerColors); +}; + +export const setLighter = (hex: string, coefficient: number) => { + const colors = hexToColors(hex); + const adjustCoefficient = coefficient > 1 ? 1 : coefficient < 0 ? 0 : coefficient; + const lighterColors = colors.map(color => Math.round(color + (255 - color) * adjustCoefficient)); + + return colorsToHex(lighterColors); +}; + +export const getLuminance = (hex: string) => { + const colors = hexToColors(hex); + const values = colors.map(color => { + const value = color / 255; + return value <= 0.03928 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4; + }); + + return Number((0.2126 * values[0] + 0.7152 * values[1] + 0.0722 * values[2]).toFixed(3)); +}; + +export const setEmphasize = (hex: string, threshold: number, coefficient = 0.15) => { + return getLuminance(hex) > threshold ? setDarker(hex, coefficient) : setLighter(hex, coefficient); +}; + +export const setOnTextColor = (hex: string, threshold: number, blackHex: string, whiteHex: string) => { + return getLuminance(hex) > threshold ? blackHex : whiteHex; +}; diff --git a/HDesign/tsconfig.json b/HDesign/tsconfig.json new file mode 100644 index 000000000..ca7b8b78f --- /dev/null +++ b/HDesign/tsconfig.json @@ -0,0 +1,34 @@ +{ + "compilerOptions": { + "sourceMap": true, + "outDir": "./dist", + "target": "ES5", + "skipLibCheck": true, + "module": "commonjs", + "moduleResolution": "node", + "strict": true, + "declaration": true, + "declarationDir": "./dist", + "resolveJsonModule": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "jsx": "react-jsx", + "allowJs": true, + "baseUrl": ".", + "paths": { + "@*": ["src/*"], + "@components/*": ["src/components/*"], + "@layouts/*": ["src/layouts/*"], + "@token/*": ["src/token/*"], + "@type/*": ["src/type/*"], + "@theme/*": ["src/theme/*"], + "@assets/*": ["src/assets/*"], + "@utils/*": ["src/utils/*"] + }, + "jsxImportSource": "@emotion/react", + "allowSyntheticDefaultImports": true + }, + "include": ["src"], + "exclude": ["./node_modules", "dist"] +} diff --git a/client/.gitignore b/client/.gitignore new file mode 100644 index 000000000..cf03bec6b --- /dev/null +++ b/client/.gitignore @@ -0,0 +1,14 @@ +logs +*.log +npm-debug.log* + +node_modules +dist + +.env.* + +*storybook.log +.DS_Store + +# Sentry Config File +.env.sentry-build-plugin diff --git a/client/.gitkeep b/client/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/client/.npmrc b/client/.npmrc new file mode 100644 index 000000000..ece05f588 --- /dev/null +++ b/client/.npmrc @@ -0,0 +1,2 @@ +engine-strict = true +legacy-peer-deps = true diff --git a/client/.prettierrc b/client/.prettierrc new file mode 100644 index 000000000..94ad823ef --- /dev/null +++ b/client/.prettierrc @@ -0,0 +1,12 @@ +{ + "singleQuote": true, + "trailingComma": "all", + "printWidth": 120, + "tabWidth": 2, + "semi": true, + "arrowParens": "avoid", + "endOfLine": "auto", + "jsxSingleQuote": false, + "bracketSpacing": false, + "proseWrap": "preserve" +} \ No newline at end of file diff --git a/client/cypress.config.ts b/client/cypress.config.ts new file mode 100644 index 000000000..2261e7871 --- /dev/null +++ b/client/cypress.config.ts @@ -0,0 +1,12 @@ +import {defineConfig} from 'cypress'; + +export default defineConfig({ + e2e: { + baseUrl: 'http://localhost:3000', + viewportWidth: 430, + viewportHeight: 930, + // setupNodeEvents(on, config) { + // // implement node event listeners here + // }, + }, +}); diff --git a/client/cypress/constants/constants.ts b/client/cypress/constants/constants.ts new file mode 100644 index 000000000..393ef5361 --- /dev/null +++ b/client/cypress/constants/constants.ts @@ -0,0 +1,6 @@ +const CONSTANTS = { + eventName: 'ํ…Œ์ŠคํŠธ ์ด๋ฒคํŠธ', + eventPassword: '1234', +}; + +export default CONSTANTS; diff --git a/client/cypress/e2e/createEvent.cy.ts b/client/cypress/e2e/createEvent.cy.ts new file mode 100644 index 000000000..5b4a93884 --- /dev/null +++ b/client/cypress/e2e/createEvent.cy.ts @@ -0,0 +1,79 @@ +import CONSTANTS from '../constants/constants'; +beforeEach(() => { + cy.blockSentry(); +}); + +describe('Flow: ๋žœ๋”ฉ ํŽ˜์ด์ง€์—์„œ๋ถ€ํ„ฐ ์ด๋ฒคํŠธ๋ฅผ ์ƒ์„ฑ ์™„๋ฃŒํ•˜๋Š” flow', () => { + it('๋žœ๋”ฉํŽ˜์ด์ง€์—์„œ "ํ–‰์‚ฌ ์ƒ์„ฑํ•˜๊ธฐ" ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ํ–‰์‚ฌ ์ด๋ฆ„ ์ž…๋ ฅ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ด์•ผ ํ•œ๋‹ค.', () => { + cy.visit('/'); + cy.get('header').find('button').click(); + cy.url().should('include', '/event/create/name'); + }); + + context('ํ–‰์‚ฌ ์ด๋ฆ„ ์ž…๋ ฅ ํŽ˜์ด์ง€', () => { + beforeEach(() => { + cy.visit('/event/create/name'); + }); + + it('ํ–‰์‚ฌ ์ด๋ฆ„ ์ž…๋ ฅ ํŽ˜์ด์ง€์—์„œ input์ด ํฌ์ปค์‹ฑ ๋˜์–ด ์žˆ๊ณ , "๋‹ค์Œ" ๋ฒ„ํŠผ์ด ๋น„ํ™œ์„ฑํ™” ๋˜์–ด ์žˆ์–ด์•ผ ํ•œ๋‹ค.', () => { + cy.get('input').focused(); + cy.get('button').contains('๋‹ค์Œ').should('have.attr', 'disabled'); + cy.url().should('include', '/event/create/name'); + }); + + it('ํ–‰์‚ฌ ์ด๋ฆ„์ด 1์ž ์ด์ƒ ์ž…๋ ฅ๋œ ๊ฒฝ์šฐ "๋‹ค์Œ" ๋ฒ„ํŠผ์ด ํ™œ์„ฑํ™” ๋˜๊ณ , ๊ฐ’์ด ์—†๋Š” ๊ฒฝ์šฐ "๋‹ค์Œ" ๋ฒ„ํŠผ์ด ๋น„ํ™œ์„ฑํ™” ๋˜์–ด์•ผ ํ•œ๋‹ค.', () => { + cy.get('input').type(CONSTANTS.eventName); + cy.get('button').contains('๋‹ค์Œ').should('not.have.attr', 'disabled'); + cy.get('input').clear(); + cy.get('input').should('have.value', ''); + cy.get('button').contains('๋‹ค์Œ').should('have.attr', 'disabled'); + cy.url().should('include', '/event/create/name'); + }); + + it('ํ–‰์‚ฌ ์ด๋ฆ„์„ ์ž…๋ ฅํ•œ ํ›„ "๋‹ค์Œ" ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ํ–‰์‚ฌ ๋น„๋ฐ€๋ฒˆํ˜ธ ์„ค์ • ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•ด์•ผ ํ•œ๋‹ค.', () => { + cy.get('input').type(CONSTANTS.eventName); + cy.get('button').contains('๋‹ค์Œ').click(); + cy.url().should('include', '/event/create/password'); + }); + }); + + context('ํ–‰์‚ฌ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ ํŽ˜์ด์ง€', () => { + beforeEach(() => { + cy.createEventName(CONSTANTS.eventName); + }); + + it('ํ–‰์‚ฌ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ ํŽ˜์ด์ง€์—์„œ input์ด ํฌ์ปค์‹ฑ ๋˜์–ด ์žˆ๊ณ , "ํ–‰๋™ ๊ฐœ์‹œ!" ๋ฒ„ํŠผ์ด ๋น„ํ™œ์„ฑํ™” ๋˜์–ด ์žˆ์–ด์•ผ ํ•œ๋‹ค.', () => { + cy.get('input').focused(); + cy.get('button').contains('ํ–‰๋™ ๊ฐœ์‹œ!').should('have.attr', 'disabled'); + cy.url().should('include', '/event/create/password'); + }); + + it('ํ–‰์‚ฌ ๋น„๋ฐ€๋ฒˆํ˜ธ์— ์ˆซ์ž๊ฐ€ ์•„๋‹Œ ์ž…๋ ฅ์„ ํ•  ๊ฒฝ์šฐ ๊ฐ’์ด ์ž…๋ ฅ๋˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.', () => { + cy.get('input').type('ํ…Œ์ŠคํŠธ'); + cy.get('input').should('have.value', ''); + }); + + it('ํ–‰์‚ฌ ๋น„๋ฐ€๋ฒˆํ˜ธ์— 4์ž๋ฆฌ ์ด์ƒ ์ž…๋ ฅ์„ ํ•  ๊ฒฝ์šฐ ์ฒ˜์Œ ๋„ค ์ž๋ฆฌ๋งŒ ์ž…๋ ฅ๋˜์–ด์•ผ ํ•œ๋‹ค.', () => { + cy.get('input').type('12345'); + cy.get('input').should('have.value', CONSTANTS.eventPassword); + }); + + it('ํ–‰์‚ฌ ๋น„๋ฐ€๋ฒˆํ˜ธ์ด 1์ž ์ด์ƒ ์ž…๋ ฅ๋œ ๊ฒฝ์šฐ "ํ–‰๋™ ๊ฐœ์‹œ!" ๋ฒ„ํŠผ์ด ํ™œ์„ฑํ™” ๋˜๊ณ , ๊ฐ’์ด ์—†๋Š” ๊ฒฝ์šฐ "ํ–‰๋™ ๊ฐœ์‹œ!" ๋ฒ„ํŠผ์ด ๋น„ํ™œ์„ฑํ™” ๋˜์–ด์•ผ ํ•œ๋‹ค.', () => { + cy.get('input').type(CONSTANTS.eventPassword); + cy.get('button').contains('ํ–‰๋™ ๊ฐœ์‹œ!').should('not.have.attr', 'disabled'); + cy.get('input').clear(); + cy.get('input').should('have.value', ''); + cy.get('button').contains('ํ–‰๋™ ๊ฐœ์‹œ!').should('have.attr', 'disabled'); + cy.url().should('include', '/event/create/password'); + }); + + it('ํ–‰์‚ฌ ๋น„๋ฐ€๋ฒˆํ˜ธ์„ ์ž…๋ ฅํ•œ ํ›„ "ํ–‰๋™ ๊ฐœ์‹œ!" ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ํ–‰์‚ฌ ์ƒ์„ฑ ์™„๋ฃŒ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•ด์•ผ ํ•œ๋‹ค.', () => { + cy.interceptAPI({type: 'postEvent', statusCode: 200}); + cy.interceptAPI({type: 'getEventName', statusCode: 200}); + cy.get('input').type(CONSTANTS.eventPassword); + cy.get('button').contains('ํ–‰๋™ ๊ฐœ์‹œ!').click(); + + cy.url().should('include', '/event/create/complete'); + }); + }); +}); diff --git a/client/cypress/fixtures/postEvent.json b/client/cypress/fixtures/postEvent.json new file mode 100644 index 000000000..63b91e17b --- /dev/null +++ b/client/cypress/fixtures/postEvent.json @@ -0,0 +1,3 @@ +{ + "eventId": "550e8400-e29b-41d4-a716-446655440000" +} \ No newline at end of file diff --git a/client/cypress/support/commands.ts b/client/cypress/support/commands.ts new file mode 100644 index 000000000..c51d00580 --- /dev/null +++ b/client/cypress/support/commands.ts @@ -0,0 +1,58 @@ +import CONSTANTS from '../constants/constants'; + +type APIType = 'sentry' | 'postEvent' | 'getEventName'; + +interface InterceptAPIProps { + type: APIType; + delay?: number; + statusCode?: number; +} +const POST_EVENT = { + method: 'POST', + url: /.*api\/events.*/, +}; + +const GET_EVENT_NAME = { + method: 'GET', + url: /.*api\/events\.*/, +}; + +Cypress.Commands.add('blockSentry', () => { + cy.intercept('POST', /.*sentry.io\/api.*/, {statusCode: 200}).as('sentry'); +}); + +Cypress.Commands.add('interceptAPI', ({type, delay = 0, statusCode = 200}: InterceptAPIProps) => { + if (type === 'postEvent') + cy.intercept(POST_EVENT, { + delay, + statusCode, + fixture: 'postEvent.json', + }).as('postEvent'); + if (type === 'getEventName') + cy.intercept(GET_EVENT_NAME, { + delay, + statusCode, + body: { + eventName: CONSTANTS.eventName, + }, + }).as('getEventName'); +}); + +Cypress.Commands.add('createEventName', (eventName: string) => { + cy.visit('/event/create/name'); + cy.get('input').type(eventName); + cy.get('button').contains('๋‹ค์Œ').click(); + cy.url().should('include', '/event/create/password'); +}); + +declare global { + namespace Cypress { + interface Chainable { + blockSentry(): Chainable; + interceptAPI(props: InterceptAPIProps): Chainable; + createEventName(eventName: string): Chainable; + } + } +} + +export {}; diff --git a/client/cypress/support/e2e.ts b/client/cypress/support/e2e.ts new file mode 100644 index 000000000..1221b17e0 --- /dev/null +++ b/client/cypress/support/e2e.ts @@ -0,0 +1 @@ +import './commands'; diff --git a/client/eslint.config.mjs b/client/eslint.config.mjs new file mode 100644 index 000000000..4ca5abb89 --- /dev/null +++ b/client/eslint.config.mjs @@ -0,0 +1,112 @@ +import {dirname} from 'path'; +import {fileURLToPath} from 'url'; +import reactPlugin from 'eslint-plugin-react'; +import tsPlugin from '@typescript-eslint/eslint-plugin'; +import importPlugin from 'eslint-plugin-import'; +import prettierPlugin from 'eslint-plugin-prettier'; +import typescriptParser from '@typescript-eslint/parser'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +export default [ + { + files: ['src/**/*.{js,jsx,ts,tsx}'], + languageOptions: { + ecmaVersion: 2021, + sourceType: 'module', + parser: typescriptParser, + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + }, + }, + plugins: { + react: reactPlugin, + '@typescript-eslint': tsPlugin, + import: importPlugin, + prettier: prettierPlugin, + }, + rules: { + 'prettier/prettier': 'error', + 'react/react-in-jsx-scope': 'off', + 'react/prop-types': 'off', + 'react/jsx-uses-vars': 'error', + // '@typescript-eslint/no-use-before-define': ['error'], + // '@typescript-eslint/explicit-module-boundary-types': 'error', + // "import/no-unresolved": "error", + 'import/order': [ + 'error', + { + 'newlines-between': 'always', + groups: ['type', 'builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'unknown'], + pathGroups: [ + { + pattern: 'react*', + group: 'external', + position: 'before', + }, + { + pattern: '@hooks/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@apis/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@store/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@pages/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@components/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@utils/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@assets/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@constants/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@mocks/*', + group: 'internal', + position: 'after', + }, + ], + }, + ], + }, + settings: { + 'import/resolver': { + node: { + extensions: ['.js', '.jsx', '.ts', '.tsx'], + }, + typescript: { + directory: './src', + }, + }, + 'import/parsers': { + '@typescript-eslint/parser': ['.ts', '.tsx'], + }, + }, + }, +]; diff --git a/client/favicon.ico b/client/favicon.ico new file mode 100644 index 000000000..2be6241f8 Binary files /dev/null and b/client/favicon.ico differ diff --git a/client/index.html b/client/index.html new file mode 100644 index 000000000..4a21293f2 --- /dev/null +++ b/client/index.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + ํ–‰๋™๋Œ€์žฅ + + +

+ + diff --git a/client/jest.config.ts b/client/jest.config.ts new file mode 100644 index 000000000..a75677a5a --- /dev/null +++ b/client/jest.config.ts @@ -0,0 +1,49 @@ +import type {Config} from 'jest'; + +const config: Config = { + preset: 'ts-jest', + // testEnvironment: 'node', // Node.js ๋ชจ๋“ˆ(fs, path, http ๋“ฑ)์„ ์‚ฌ์šฉํ•œ ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋กœ์ง์ด๋‚˜ ํŒŒ์ผ ์‹œ์Šคํ…œ ์ ‘๊ทผ, ๋„คํŠธ์›Œํฌ ์š”์ฒญ ๋“ฑ์„ ํ…Œ์ŠคํŠธ + testEnvironment: 'jsdom', // ๋ธŒ๋ผ์šฐ์ € ๋‚ด์—์„œ์˜ JavaScript ๋™์ž‘์„ ๋ชจ๋ฐฉํ•˜์—ฌ, DOM ์กฐ์ž‘, ์ด๋ฒคํŠธ ํ•ธ๋“ค๋ง, ๋ธŒ๋ผ์šฐ์ € ๊ด€๋ จ API ํ˜ธ์ถœ + transform: { + '^.+\\.ts?$': 'ts-jest', + }, + collectCoverage: true, + coverageReporters: ['text'], + coveragePathIgnorePatterns: [ + '/node_modules/', + '/src/utils/', + '/src/mocks/', + '/src/apis/', + '/src/request/', + '/src/constants/', + '/src/errors/', + '/src/components/', + '/src/store/', + '/src/pages/', + '/src/hooks/queries', + ], + + verbose: true, + setupFiles: ['./jest.polyfills.ts'], + setupFilesAfterEnv: ['./jest.setup.ts'], + transformIgnorePatterns: ['/node_modules/'], + moduleNameMapper: { + '@/(.*)$': '/src/$1', // path alias๋ฅผ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•จ + '^@apis/(.*)$': '/src/apis/$1', + '^@constants/(.*)$': '/src/constants/$1', + '^@components/(.*)$': '/src/components/$1', + '^@hooks/(.*)$': '/src/hooks/$1', + '^@utils/(.*)$': '/src/utils/$1', + '^@pages/(.*)$': '/src/pages/$1', + '^@types/(.*)$': '/src/types/$1', + '^@errors/(.*)$': '/src/errors/$1', + '^@mocks/(.*)$': '/src/mocks/$1', + '^@store/(.*)$': '/src/store/$1', + '\\.svg$': '/src/mocks/svg.ts', + }, + testEnvironmentOptions: { + customExportConditions: [''], + }, +}; + +export default config; diff --git a/client/jest.polyfills.ts b/client/jest.polyfills.ts new file mode 100644 index 000000000..16547bc80 --- /dev/null +++ b/client/jest.polyfills.ts @@ -0,0 +1,20 @@ +import {TextDecoder, TextEncoder} from 'node:util'; + +Object.defineProperties(globalThis, { + TextDecoder: {value: TextDecoder}, + TextEncoder: {value: TextEncoder}, +}); + +import {Blob, File} from 'node:buffer'; + +import {fetch, Headers, FormData, Request, Response} from 'undici'; + +Object.defineProperties(globalThis, { + fetch: {value: fetch, writable: true}, + Blob: {value: Blob}, + File: {value: File}, + Headers: {value: Headers}, + FormData: {value: FormData}, + Request: {value: Request}, + Response: {value: Response}, +}); diff --git a/client/jest.setup.ts b/client/jest.setup.ts new file mode 100644 index 000000000..33c8f6a70 --- /dev/null +++ b/client/jest.setup.ts @@ -0,0 +1,24 @@ +import {server} from './src/mocks/server'; +import * as router from 'react-router'; +import '@testing-library/jest-dom'; // toBeInTheDocument๋ฅผ ์ธ์‹ํ•˜๊ธฐ ์œ„ํ•ด @testing-library/jest-dom/extend-expect์ถ”๊ฐ€ +import 'jest-canvas-mock'; // jsdom์€ canvas๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€ + +beforeAll(() => { + server.listen(); + + Object.defineProperty(window, 'location', { + writable: true, + value: { + ...window.location, + pathname: '/event/abc-123/', // ์›ํ•˜๋Š” pathname ์„ค์ • + }, + }); +}); +afterEach(() => server.resetHandlers()); +afterAll(() => server.close()); + +beforeAll(() => {}); +jest.mock('./src/utils/captureError'); +jest.mock('./src/utils/sendLogToSentry'); + +jest.spyOn(router, 'useNavigate').mockImplementation(() => jest.fn()); diff --git a/client/package-lock.json b/client/package-lock.json new file mode 100644 index 000000000..61a529538 --- /dev/null +++ b/client/package-lock.json @@ -0,0 +1,19037 @@ +{ + "name": "haengdong-client", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "haengdong-client", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@emotion/react": "^11.11.4", + "@sentry/react": "^8.25.0", + "@tanstack/react-query": "^5.51.23", + "haengdong-design": "^0.1.81", + "jest-canvas-mock": "^2.5.2", + "react": "^18.3.1", + "react-copy-to-clipboard": "^5.1.0", + "react-dom": "^18.3.1", + "react-error-boundary": "^4.0.13", + "react-router-dom": "^6.24.1", + "zustand": "^4.5.5" + }, + "devDependencies": { + "@eslint/compat": "^1.1.0", + "@eslint/js": "^9.6.0", + "@jest/types": "^29.6.3", + "@sentry/webpack-plugin": "^2.22.0", + "@svgr/webpack": "^8.1.0", + "@tanstack/react-query-devtools": "^5.52.0", + "@testing-library/dom": "^10.4.0", + "@testing-library/jest-dom": "^6.4.8", + "@testing-library/react": "^16.0.0", + "@types/dotenv-webpack": "^7.0.7", + "@types/jest": "^29.5.12", + "@types/react": "^18.3.3", + "@types/react-copy-to-clipboard": "^5.0.7", + "@types/react-dom": "^18.3.0", + "@types/testing-library__jest-dom": "^6.0.0", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "cypress": "^13.13.2", + "dotenv-webpack": "^8.1.0", + "eslint": "^9.6.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-jsx-a11y": "^6.9.0", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-react": "^7.34.3", + "eslint-plugin-react-hooks": "^4.6.2", + "fork-ts-checker-webpack-plugin": "^9.0.2", + "globals": "^15.8.0", + "html-loader": "^5.0.0", + "html-webpack-plugin": "^5.6.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "jsdom": "^24.1.1", + "modify-source-webpack-plugin": "^4.1.0", + "msw": "^2.3.5", + "prettier": "3.3.2", + "ts-jest": "^29.2.4", + "ts-loader": "^9.5.1", + "ts-node": "^10.9.2", + "typescript": "^5.5.4", + "typescript-eslint": "^7.16.0", + "undici": "^5.28.4", + "webpack": "^5.93.0", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^5.0.4", + "webpack-merge": "^6.0.1" + }, + "engines": { + "node": ">=20.15.1", + "npm": ">=10.7.0" + } + }, + "node_modules/@adobe/css-tools": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", + "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==", + "dev": true + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.2.tgz", + "integrity": "sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", + "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-module-transforms": "^7.25.2", + "@babel/helpers": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.2", + "@babel/types": "^7.25.2", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/@babel/generator": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz", + "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==", + "dependencies": { + "@babel/types": "^7.25.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", + "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", + "dependencies": { + "@babel/compat-data": "^7.25.2", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.0.tgz", + "integrity": "sha512-GYM6BxeQsETc9mnct+nIIpf63SAyzvyYN7UB/IlTyd+MBg06afFGp0mIeUqGyWgS2mxad6vqbMrHVlaL3m70sQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/traverse": "^7.25.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz", + "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", + "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "dependencies": { + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", + "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", + "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-wrap-function": "^7.25.0", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", + "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", + "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", + "dependencies": { + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.0", + "@babel/types": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz", + "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==", + "dependencies": { + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz", + "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==", + "dependencies": { + "@babel/types": "^7.25.2" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz", + "integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz", + "integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz", + "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", + "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz", + "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", + "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", + "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", + "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", + "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", + "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.0.tgz", + "integrity": "sha512-uaIi2FdqzjpAMvVqvB51S42oC2JEVgh0LDsGfZVDysWE8LrJtQC2jvKmOqEYThKyB7bDEb7BP1GYWDm7tABA0Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-remap-async-to-generator": "^7.25.0", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", + "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", + "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz", + "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", + "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", + "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.0.tgz", + "integrity": "sha512-xyi6qjr/fYU304fiRwFbekzkqVJZ6A7hOjWZd+89FVcBqPV3S9Wuozz82xdpLspckeaafntbzglaW4pqpzvtSw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/traverse": "^7.25.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", + "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/template": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", + "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", + "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", + "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz", + "integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", + "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", + "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", + "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", + "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz", + "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", + "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz", + "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", + "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", + "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", + "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", + "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-simple-access": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz", + "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", + "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", + "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", + "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", + "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", + "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", + "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", + "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", + "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", + "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", + "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", + "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", + "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.25.1.tgz", + "integrity": "sha512-SLV/giH/V4SmloZ6Dt40HjTGTAIkxn33TVIHxNGNvo8ezMhrxBkzisj4op1KZYPIOHFLqhv60OHvX+YRu4xbmQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", + "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.2.tgz", + "integrity": "sha512-KQsqEAVBpU82NM/B/N9j9WOdphom1SZH3R+2V7INrQUH+V9EBFwZsEJl8eBIVeQE62FxJCc70jzEZwqU7RcVqA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/types": "^7.25.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", + "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz", + "integrity": "sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", + "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", + "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", + "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", + "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", + "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", + "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", + "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.2.tgz", + "integrity": "sha512-lBwRvjSmqiMYe/pS0+1gggjJleUJi7NzjvQ1Fkqtt69hBa/0t1YuW/MLQMAPixfwaQOHUXsd6jeU3Z+vdGv3+A==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", + "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", + "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", + "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", + "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.3.tgz", + "integrity": "sha512-QsYW7UeAaXvLPX9tdVliMJE7MD7M6MLYVTovRTIwhoYQVFHR1rM4wO8wqAezYi3/BpSD+NzVCZ69R6smWiIi8g==", + "dependencies": { + "@babel/compat-data": "^7.25.2", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.3", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.0", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.24.7", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.0", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoped-functions": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.25.0", + "@babel/plugin-transform-class-properties": "^7.24.7", + "@babel/plugin-transform-class-static-block": "^7.24.7", + "@babel/plugin-transform-classes": "^7.25.0", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-dotall-regex": "^7.24.7", + "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.0", + "@babel/plugin-transform-dynamic-import": "^7.24.7", + "@babel/plugin-transform-exponentiation-operator": "^7.24.7", + "@babel/plugin-transform-export-namespace-from": "^7.24.7", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.25.1", + "@babel/plugin-transform-json-strings": "^7.24.7", + "@babel/plugin-transform-literals": "^7.25.2", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-member-expression-literals": "^7.24.7", + "@babel/plugin-transform-modules-amd": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-modules-systemjs": "^7.25.0", + "@babel/plugin-transform-modules-umd": "^7.24.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-new-target": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-object-super": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-property-literals": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-reserved-words": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-template-literals": "^7.24.7", + "@babel/plugin-transform-typeof-symbol": "^7.24.8", + "@babel/plugin-transform-unicode-escapes": "^7.24.7", + "@babel/plugin-transform-unicode-property-regex": "^7.24.7", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.37.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", + "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.24.7", + "@babel/plugin-transform-react-jsx-development": "^7.24.7", + "@babel/plugin-transform-react-pure-annotations": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", + "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + }, + "node_modules/@babel/runtime": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz", + "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.3.tgz", + "integrity": "sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/parser": "^7.25.3", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.2", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", + "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", + "dependencies": { + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@bundled-es-modules/cookie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.0.tgz", + "integrity": "sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw==", + "dev": true, + "dependencies": { + "cookie": "^0.5.0" + } + }, + "node_modules/@bundled-es-modules/cookie/node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@bundled-es-modules/statuses": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz", + "integrity": "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==", + "dev": true, + "dependencies": { + "statuses": "^2.0.1" + } + }, + "node_modules/@bundled-es-modules/tough-cookie": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/tough-cookie/-/tough-cookie-0.1.6.tgz", + "integrity": "sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==", + "dev": true, + "dependencies": { + "@types/tough-cookie": "^4.0.5", + "tough-cookie": "^4.1.4" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@cypress/request": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz", + "integrity": "sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==", + "dev": true, + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "http-signature": "~1.3.6", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "performance-now": "^2.1.0", + "qs": "6.10.4", + "safe-buffer": "^5.1.2", + "tough-cookie": "^4.1.3", + "tunnel-agent": "^0.6.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@cypress/request/node_modules/qs": { + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", + "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@cypress/xvfb": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", + "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", + "dev": true, + "dependencies": { + "debug": "^3.1.0", + "lodash.once": "^4.1.1" + } + }, + "node_modules/@cypress/xvfb/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz", + "integrity": "sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.2.0", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.13.1", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz", + "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==" + }, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" + }, + "node_modules/@emotion/react": { + "version": "11.13.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.0.tgz", + "integrity": "sha512-WkL+bw1REC2VNV1goQyfxjx1GYJkcc23CRQkXX+vZNLINyfI7o+uUn/rTGPt/xJ3bJHd5GcljgnxHf4wRw5VWQ==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.12.0", + "@emotion/cache": "^11.13.0", + "@emotion/serialize": "^1.3.0", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.0.tgz", + "integrity": "sha512-jACuBa9SlYajnpIVXB+XOXnfJHyckDfe6fOpORIM6yhBDlqGuExvDdZYHDQGoDf3bZXGv7tNr+LpLjJqiEQ6EA==", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.9.0", + "@emotion/utils": "^1.4.0", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==" + }, + "node_modules/@emotion/unitless": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.9.0.tgz", + "integrity": "sha512-TP6GgNZtmtFaFcsOgExdnfxLLpRDla4Q66tnenA9CktvVSdNKDvMVuUah4QvWPIpNjrWsGg3qeGo9a43QooGZQ==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz", + "integrity": "sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.0.tgz", + "integrity": "sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ==" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==" + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/compat": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.1.tgz", + "integrity": "sha512-lpHyRyplhGPL5mGEh6M9O5nnKk0Gz4bFI+Zu6tKlPpDUN7XshWvH9C/px4UVm87IAANE0W81CEsNGbS1KlzXpA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", + "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", + "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@inquirer/confirm": { + "version": "3.1.22", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.22.tgz", + "integrity": "sha512-gsAKIOWBm2Q87CDfs9fEo7wJT3fwWIJfnDGMn9Qy74gBnNFOACDNfhUzovubbJjWnKLGBln7/NcSmZwj5DuEXg==", + "dev": true, + "dependencies": { + "@inquirer/core": "^9.0.10", + "@inquirer/type": "^1.5.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/core": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.10.tgz", + "integrity": "sha512-TdESOKSVwf6+YWDz8GhS6nKscwzkIyakEzCLJ5Vh6O3Co2ClhCJ0A4MG909MUWfaWdpJm7DE45ii51/2Kat9tA==", + "dev": true, + "dependencies": { + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.2", + "@types/mute-stream": "^0.0.4", + "@types/node": "^22.1.0", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "cli-spinners": "^2.9.2", + "cli-width": "^4.1.0", + "mute-stream": "^1.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@inquirer/core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@inquirer/core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@inquirer/core/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@inquirer/core/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.5.tgz", + "integrity": "sha512-79hP/VWdZ2UVc9bFGJnoQ/lQMpL74mGgzSYX1xUqCVk7/v73vJCMw1VuyWN1jGkZ9B3z7THAbySqGbCNefcjfA==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/type": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.5.2.tgz", + "integrity": "sha512-w9qFkumYDCNyDZmNQjf/n6qQuvQ4dMC3BJesY4oF+yr0CxR5vxujflAVeIcS6U336uzi9GM0kAfZlLrZ9UTkpA==", + "dev": true, + "dependencies": { + "mute-stream": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/console/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/console/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/core/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/transform/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/transform/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/@jest/transform/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/types/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsonjoy.com/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.0.4.tgz", + "integrity": "sha512-aOcSN4MeAtFROysrbqG137b7gaDDSmVrl5mpo6sT/w+kcXpWnzhMjmY/Fh/sDx26NBxyIE7MB1seqLeCAzy9Sg==", + "dev": true, + "dependencies": { + "@jsonjoy.com/base64": "^1.1.1", + "@jsonjoy.com/util": "^1.1.2", + "hyperdyperid": "^1.2.0", + "thingies": "^1.20.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.3.0.tgz", + "integrity": "sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "dev": true + }, + "node_modules/@mswjs/interceptors": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.29.1.tgz", + "integrity": "sha512-3rDakgJZ77+RiQUuSK69t1F0m8BQKA8Vh5DCS5V0DWvNY67zob2JhhQrhCO0AKLGINTRSFd1tBaHcJTkhefoSw==", + "dev": true, + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.2.1", + "strict-event-emitter": "^0.5.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "dev": true + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "dev": true, + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "dev": true + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@remix-run/router": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.0.tgz", + "integrity": "sha512-zDICCLKEwbVYTS6TjYaWtHXxkdoUvD/QXvyVZjGCsWz5vyH7aFeONlPffPdW+Y/t6KT0MgXb2Mfjun9YpWN1dA==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@sentry-internal/browser-utils": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.25.0.tgz", + "integrity": "sha512-nlWgp1lVhNQOTUplW85G3qm0fOIgAhJ/sl/31OIuScVrITYhYDF2bO+Zv/jQ8YsdUBAUXqY1tPT9wwPJklnPhw==", + "dependencies": { + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/feedback": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.25.0.tgz", + "integrity": "sha512-327I5XJAFrsgjc5qUKxZ9rff3WNCfGvf1fIii70LQ2YQhQgG4XHZILmkD06ETEyXb+H1tkrNQQEJ1/d4ai+q5g==", + "dependencies": { + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/replay": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.25.0.tgz", + "integrity": "sha512-3f7x8EYthyj157uV9V8vBjun+1gJnHhh2+i0qxYLhMGx7N2Fq0J3Bvvo1rosSg+fYh5HzPNZDufwIRdg5C/MQw==", + "dependencies": { + "@sentry-internal/browser-utils": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/replay-canvas": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.25.0.tgz", + "integrity": "sha512-dPXlkAbkFL1DBum8rGTaHS+apJKaXEZJF9gLcBBKTruhTCizrugFLxajzIfVSiFVuwNKuJWa2fzhzbeQM0ee7w==", + "dependencies": { + "@sentry-internal/replay": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/babel-plugin-component-annotate": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.22.0.tgz", + "integrity": "sha512-UzH+NNhgnOo6UFku3C4TEz+pO/yDcIA5FKTJvLbJ7lQwAjsqLs3DZWm4cCA08skICb8mULArF6S/dn5/butVCA==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/browser": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.25.0.tgz", + "integrity": "sha512-51bdVGXjyooqVGzaSGsnExqRTt9NvZ1zGFsxbbCSXi5UoEFN6zdMUz6jKYsL2K80eeELP2VKOVlobHlEzeJQfw==", + "dependencies": { + "@sentry-internal/browser-utils": "8.25.0", + "@sentry-internal/feedback": "8.25.0", + "@sentry-internal/replay": "8.25.0", + "@sentry-internal/replay-canvas": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/bundler-plugin-core": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.22.0.tgz", + "integrity": "sha512-/xXN8o7565WMsewBnQFfjm0E5wqhYsegg++HJ5RjrY/cTM4qcd/ven44GEMxqGFJitZizvkk3NHszaHylzcRUw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.18.5", + "@sentry/babel-plugin-component-annotate": "2.22.0", + "@sentry/cli": "^2.33.1", + "dotenv": "^16.3.1", + "find-up": "^5.0.0", + "glob": "^9.3.2", + "magic-string": "0.30.8", + "unplugin": "1.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/cli": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.33.1.tgz", + "integrity": "sha512-dUlZ4EFh98VFRPJ+f6OW3JEYQ7VvqGNMa0AMcmvk07ePNeK/GicAWmSQE4ZfJTTl80ul6HZw1kY01fGQOQlVRA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.7", + "progress": "^2.0.3", + "proxy-from-env": "^1.1.0", + "which": "^2.0.2" + }, + "bin": { + "sentry-cli": "bin/sentry-cli" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@sentry/cli-darwin": "2.33.1", + "@sentry/cli-linux-arm": "2.33.1", + "@sentry/cli-linux-arm64": "2.33.1", + "@sentry/cli-linux-i686": "2.33.1", + "@sentry/cli-linux-x64": "2.33.1", + "@sentry/cli-win32-i686": "2.33.1", + "@sentry/cli-win32-x64": "2.33.1" + } + }, + "node_modules/@sentry/cli-darwin": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.33.1.tgz", + "integrity": "sha512-+4/VIx/E1L2hChj5nGf5MHyEPHUNHJ/HoG5RY+B+vyEutGily1c1+DM2bum7RbD0xs6wKLIyup5F02guzSzG8A==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.33.1.tgz", + "integrity": "sha512-zbxEvQju+tgNvzTOt635le4kS/Fbm2XC2RtYbCTs034Vb8xjrAxLnK0z1bQnStUV8BkeBHtsNVrG+NSQDym2wg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.33.1.tgz", + "integrity": "sha512-DbGV56PRKOLsAZJX27Jt2uZ11QfQEMmWB4cIvxkKcFVE+LJP4MVA+MGGRUL6p+Bs1R9ZUuGbpKGtj0JiG6CoXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-i686": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.33.1.tgz", + "integrity": "sha512-g2LS4oPXkPWOfKWukKzYp4FnXVRRSwBxhuQ9eSw2peeb58ZIObr4YKGOA/8HJRGkooBJIKGaAR2mH2Pk1TKaiA==", + "cpu": [ + "x86", + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-x64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.33.1.tgz", + "integrity": "sha512-IV3dcYV/ZcvO+VGu9U6kuxSdbsV2kzxaBwWUQxtzxJ+cOa7J8Hn1t0koKGtU53JVZNBa06qJWIcqgl4/pCuKIg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-i686": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.33.1.tgz", + "integrity": "sha512-F7cJySvkpzIu7fnLKNHYwBzZYYwlhoDbAUnaFX0UZCN+5DNp/5LwTp37a5TWOsmCaHMZT4i9IO4SIsnNw16/zQ==", + "cpu": [ + "x86", + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-x64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.33.1.tgz", + "integrity": "sha512-8VyRoJqtb2uQ8/bFRKNuACYZt7r+Xx0k2wXRGTyH05lCjAiVIXn7DiS2BxHFty7M1QEWUCMNsb/UC/x/Cu2wuA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/core": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.25.0.tgz", + "integrity": "sha512-7KtglbrW1eX4DOHkf6i4rRIExEf2CgtQ99qZ8gn5FUaAmNMg0rK7bb1yZMx0RZtp5G1TSz/S0jQQgxHWebaEig==", + "dependencies": { + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/react": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-8.25.0.tgz", + "integrity": "sha512-A3QeSCJEa+lpo5nh0kxKeqsmnuW2nycKNN/0bpXPv5T5jiEfExSmEBVM0zutrQpf+J0WRIl1AGunUYGPO+GPQg==", + "dependencies": { + "@sentry/browser": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0", + "hoist-non-react-statics": "^3.3.2" + }, + "engines": { + "node": ">=14.18" + }, + "peerDependencies": { + "react": "^16.14.0 || 17.x || 18.x || 19.x" + } + }, + "node_modules/@sentry/types": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.25.0.tgz", + "integrity": "sha512-ojim0gDcRhGJPguYrtms4FsprX4xZz3LGNk9Z0hwTbSVEdlhQIInsQ7CYcdM3sjUs+qT7kfpxTRZGUeZNRRJcA==", + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/utils": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.25.0.tgz", + "integrity": "sha512-mVlkV7S62ZZ2jM38/kOwWx2xoW8fUv2cjw2IwFKoAIPyLBh3mo1WJtvfdtN/rXGjQWZJBKW53EWaWnD00rkjyA==", + "dependencies": { + "@sentry/types": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/webpack-plugin": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-2.22.0.tgz", + "integrity": "sha512-u2brctki0AMCoZksdAConQSYE6PokRVeZ4YYsbnJYkAi0KuaQnczsRwS9e2L0bK2CmZ7QdyYcrjaXHNlXaFDbQ==", + "dev": true, + "dependencies": { + "@sentry/bundler-plugin-core": "2.22.0", + "unplugin": "1.0.1", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "webpack": ">=4.40.0" + } + }, + "node_modules/@sentry/webpack-plugin/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@storybook/addon-webpack5-compiler-swc": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-swc/-/addon-webpack5-compiler-swc-1.0.5.tgz", + "integrity": "sha512-1NlM3noit2vA22OyWb8Ma2lhcEKCS1Snv2kr+EkaVABUqNDfVc9AD/GgYQhF7F/2CoF5N2JU7uzXDzFHd5TzZg==", + "dependencies": { + "@swc/core": "^1.7.3", + "swc-loader": "^0.2.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", + "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", + "dependencies": { + "cosmiconfig": "^8.1.3", + "deepmerge": "^4.3.1", + "svgo": "^3.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", + "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", + "dependencies": { + "@babel/core": "^7.21.3", + "@babel/plugin-transform-react-constant-elements": "^7.21.3", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@svgr/core": "8.1.0", + "@svgr/plugin-jsx": "8.1.0", + "@svgr/plugin-svgo": "8.1.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@swc/core": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.14.tgz", + "integrity": "sha512-9aeXeifnyuvc2pcuuhPQgVUwdpGEzZ+9nJu0W8/hNl/aESFsJGR5i9uQJRGu0atoNr01gK092fvmqMmQAPcKow==", + "hasInstallScript": true, + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.12" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.7.14", + "@swc/core-darwin-x64": "1.7.14", + "@swc/core-linux-arm-gnueabihf": "1.7.14", + "@swc/core-linux-arm64-gnu": "1.7.14", + "@swc/core-linux-arm64-musl": "1.7.14", + "@swc/core-linux-x64-gnu": "1.7.14", + "@swc/core-linux-x64-musl": "1.7.14", + "@swc/core-win32-arm64-msvc": "1.7.14", + "@swc/core-win32-ia32-msvc": "1.7.14", + "@swc/core-win32-x64-msvc": "1.7.14" + }, + "peerDependencies": { + "@swc/helpers": "*" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.14.tgz", + "integrity": "sha512-V0OUXjOH+hdGxDYG8NkQzy25mKOpcNKFpqtZEzLe5V/CpLJPnpg1+pMz70m14s9ZFda9OxsjlvPbg1FLUwhgIQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.14.tgz", + "integrity": "sha512-9iFvUnxG6FC3An5ogp5jbBfQuUmTTwy8KMB+ZddUoPB3NR1eV+Y9vOh/tfWcenSJbgOKDLgYC5D/b1mHAprsrQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.14.tgz", + "integrity": "sha512-zGJsef9qPivKSH8Vv4F/HiBXBTHZ5Hs3ZjVGo/UIdWPJF8fTL9OVADiRrl34Q7zOZEtGXRwEKLUW1SCQcbDvZA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.14.tgz", + "integrity": "sha512-AxV3MPsoI7i4B8FXOew3dx3N8y00YoJYvIPfxelw07RegeCEH3aHp2U2DtgbP/NV1ugZMx0TL2Z2DEvocmA51g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.14.tgz", + "integrity": "sha512-JDLdNjUj3zPehd4+DrQD8Ltb3B5lD8D05IwePyDWw+uR/YPc7w/TX1FUVci5h3giJnlMCJRvi1IQYV7K1n7KtQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.14.tgz", + "integrity": "sha512-Siy5OvPCLLWmMdx4msnEs8HvEVUEigSn0+3pbLjv78iwzXd0qSBNHUPZyC1xeurVaUbpNDxZTpPRIwpqNE2+Og==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.14.tgz", + "integrity": "sha512-FtEGm9mwtRYQNK43WMtUIadxHs/ja2rnDurB99os0ZoFTGG2IHuht2zD97W0wB8JbqEabT1XwSG9Y5wmN+ciEQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.14.tgz", + "integrity": "sha512-Jp8KDlfq7Ntt2/BXr0y344cYgB1zf0DaLzDZ1ZJR6rYlAzWYSccLYcxHa97VGnsYhhPspMpmCvHid97oe2hl4A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.14.tgz", + "integrity": "sha512-I+cFsXF0OU0J9J4zdWiQKKLURO5dvCujH9Jr8N0cErdy54l9d4gfIxdctfTF+7FyXtWKLTCkp+oby9BQhkFGWA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.14.tgz", + "integrity": "sha512-NNrprQCK6d28mG436jVo2TD+vACHseUECacEBGZ9Ef0qfOIWS1XIt2MisQKG0Oea2VvLFl6tF/V4Lnx/H0Sn3Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" + }, + "node_modules/@swc/types": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", + "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, + "node_modules/@tanstack/query-core": { + "version": "5.51.21", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.51.21.tgz", + "integrity": "sha512-POQxm42IUp6n89kKWF4IZi18v3fxQWFRolvBA6phNVmA8psdfB1MvDnGacCJdS+EOX12w/CyHM62z//rHmYmvw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/query-devtools": { + "version": "5.51.16", + "resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.51.16.tgz", + "integrity": "sha512-ajwuq4WnkNCMj/Hy3KR8d3RtZ6PSKc1dD2vs2T408MdjgKzQ3klVoL6zDgVO7X+5jlb5zfgcO3thh4ojPhfIaw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.51.23", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.51.23.tgz", + "integrity": "sha512-CfJCfX45nnVIZjQBRYYtvVMIsGgWLKLYC4xcUiYEey671n1alvTZoCBaU9B85O8mF/tx9LPyrI04A6Bs2THv4A==", + "dependencies": { + "@tanstack/query-core": "5.51.21" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/@tanstack/react-query-devtools": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.52.0.tgz", + "integrity": "sha512-oq8bDxMQ95edOlcWFaGsnSFzH11s06M1uiNiLtgsm+UG6Y5w+K6BJp0GeXN8q7sBNVBw/WPyeFdUH8rj9RT2Aw==", + "dev": true, + "dependencies": { + "@tanstack/query-devtools": "5.51.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "@tanstack/react-query": "^5.52.0", + "react": "^18 || ^19" + } + }, + "node_modules/@testing-library/dom": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/@testing-library/dom/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@testing-library/dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/dom/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/@testing-library/dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.8.tgz", + "integrity": "sha512-JD0G+Zc38f5MBHA4NgxQMR5XtO5Jx9g86jqturNTt2WUfRmLDIY7iKkWHDCCTiDuFMre6nxAD5wHw9W5kI4rGw==", + "dev": true, + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "@babel/runtime": "^7.9.2", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true + }, + "node_modules/@testing-library/jest-dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/react": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.0.0.tgz", + "integrity": "sha512-guuxUKRWQ+FgNX0h0NS0FIq3Q3uLtWVpBzcLOggmfMoUpgBnzBzvLLd4fbm6yS8ydJd94cIfY4yP9qUQjM2KwQ==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "dev": true, + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "dev": true + }, + "node_modules/@types/dotenv-webpack": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@types/dotenv-webpack/-/dotenv-webpack-7.0.7.tgz", + "integrity": "sha512-tltVokFUeYuSjNmHc6N892Asu/JIQcnH2iUF5A29/VKqv9opq6KlrmnKd/Lt/bBikV/z0YN2K0kguTwWirYCMQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "tapable": "^2.2.0", + "webpack": "^5" + } + }, + "node_modules/@types/eslint": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", + "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.5", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", + "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "node_modules/@types/http-proxy": { + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/jsdom": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", + "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/mute-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz", + "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", + "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", + "dev": true, + "dependencies": { + "undici-types": "~6.13.0" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "dev": true + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/react": { + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-copy-to-clipboard": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.7.tgz", + "integrity": "sha512-Gft19D+as4M+9Whq1oglhmK49vqPhcLzk8WfvfLvaYMIPYanyfLy0+CwFucMJfdKoSFyySPmkkWn8/E6voQXjQ==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", + "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==", + "dev": true + }, + "node_modules/@types/sizzle": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.8.tgz", + "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==", + "dev": true + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true + }, + "node_modules/@types/statuses": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.5.tgz", + "integrity": "sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==", + "dev": true + }, + "node_modules/@types/testing-library__jest-dom": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-6.0.0.tgz", + "integrity": "sha512-bnreXCgus6IIadyHNlN/oI5FfX4dWgvGhOPvpr7zzCYDGAPIfvyIoAozMBINmhmsVuqV0cncejF2y5KC7ScqOg==", + "deprecated": "This is a stub types definition. @testing-library/jest-dom provides its own type definitions, so you do not need this installed.", + "dev": true, + "dependencies": { + "@testing-library/jest-dom": "*" + } + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "dev": true + }, + "node_modules/@types/wrap-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", + "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==", + "dev": true + }, + "node_modules/@types/ws": { + "version": "8.5.12", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", + "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", + "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/type-utils": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", + "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", + "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", + "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", + "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", + "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", + "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", + "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "dev": true, + "dependencies": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "dev": true, + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "dev": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.1.tgz", + "integrity": "sha512-u5w79Rd7SU4JaIlA/zFqG+gOiuq25q5VLyZ8E+ijJeILuTxVzZgp2CaGw/UTw6pXYN9XMO9yiqj/nEHmhTG5CA==", + "dev": true + }, + "node_modules/axe-core": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.0.tgz", + "integrity": "sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/babel-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/babel-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/babel-plugin-macros/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/blob-util": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", + "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", + "dev": true + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/bonjour-service": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", + "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cachedir": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", + "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "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" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001649", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001649.tgz", + "integrity": "sha512-fJegqZZ0ZX8HOWr6rcafGr72+xcgJKI9oWfDW5DrD7ExUtgZC7a7R7ZYmZqplh7XDocFdGeIFn7roAxhOeYrPQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", + "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", + "dev": true + }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-table3/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cli-table3/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/cliui/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, + "node_modules/copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, + "node_modules/core-js-compat": { + "version": "3.38.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.0.tgz", + "integrity": "sha512-75LAicdLa4OJVwFxFbQR3NdnZjNgX6ILpVcVzcC4T2smerB5lELMrJQQQoWV6TiuC/vlaFqgU2tKQx9w5s0e0A==", + "dependencies": { + "browserslist": "^4.23.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/create-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/create-jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/create-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/create-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/create-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true + }, + "node_modules/cssfontparser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/cssfontparser/-/cssfontparser-1.2.1.tgz", + "integrity": "sha512-6tun4LoZnj7VN6YeegOVb67KBX/7JJsqvj+pv3ZA7F878/eN33AbGa5b/S/wXxS/tcp8nc40xRUrsPlxIyNUPg==" + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" + }, + "node_modules/cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "dev": true + }, + "node_modules/cssstyle": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz", + "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==", + "dev": true, + "dependencies": { + "rrweb-cssom": "^0.6.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cssstyle/node_modules/rrweb-cssom": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", + "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", + "dev": true + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/cypress": { + "version": "13.13.2", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.13.2.tgz", + "integrity": "sha512-PvJQU33933NvS1StfzEb8/mu2kMy4dABwCF+yd5Bi7Qly1HOVf+Bufrygee/tlmty/6j5lX+KIi8j9Q3JUMbhA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@cypress/request": "^3.0.1", + "@cypress/xvfb": "^1.2.4", + "@types/sinonjs__fake-timers": "8.1.1", + "@types/sizzle": "^2.3.2", + "arch": "^2.2.0", + "blob-util": "^2.0.2", + "bluebird": "^3.7.2", + "buffer": "^5.7.1", + "cachedir": "^2.3.0", + "chalk": "^4.1.0", + "check-more-types": "^2.24.0", + "cli-cursor": "^3.1.0", + "cli-table3": "~0.6.1", + "commander": "^6.2.1", + "common-tags": "^1.8.0", + "dayjs": "^1.10.4", + "debug": "^4.3.4", + "enquirer": "^2.3.6", + "eventemitter2": "6.4.7", + "execa": "4.1.0", + "executable": "^4.1.1", + "extract-zip": "2.0.1", + "figures": "^3.2.0", + "fs-extra": "^9.1.0", + "getos": "^3.2.1", + "is-ci": "^3.0.1", + "is-installed-globally": "~0.4.0", + "lazy-ass": "^1.6.0", + "listr2": "^3.8.3", + "lodash": "^4.17.21", + "log-symbols": "^4.0.0", + "minimist": "^1.2.8", + "ospath": "^1.2.2", + "pretty-bytes": "^5.6.0", + "process": "^0.11.10", + "proxy-from-env": "1.0.0", + "request-progress": "^3.0.0", + "semver": "^7.5.3", + "supports-color": "^8.1.1", + "tmp": "~0.2.3", + "untildify": "^4.0.0", + "yauzl": "^2.10.0" + }, + "bin": { + "cypress": "bin/cypress" + }, + "engines": { + "node": "^16.0.0 || ^18.0.0 || >=20.0.0" + } + }, + "node_modules/cypress/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cypress/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cypress/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cypress/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/cypress/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/cypress/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/cypress/node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/cypress/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cypress/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cypress/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cypress/node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true, + "engines": { + "node": ">=8.12.0" + } + }, + "node_modules/cypress/node_modules/proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", + "dev": true + }, + "node_modules/cypress/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cypress/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-urls/node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dev": true, + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-urls/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "dev": true, + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dayjs": { + "version": "1.11.12", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.12.tgz", + "integrity": "sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true + }, + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", + "dev": true, + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dev": true, + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "deprecated": "Use your platform's native DOMException instead", + "dev": true, + "dependencies": { + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dotenv-defaults": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dotenv-defaults/-/dotenv-defaults-2.0.2.tgz", + "integrity": "sha512-iOIzovWfsUHU91L5i8bJce3NYK5JXeAwH50Jh6+ARUdLiiGlYWfGw6UkzsYqaXZH/hjE/eCd/PlfM/qqyK0AMg==", + "dev": true, + "dependencies": { + "dotenv": "^8.2.0" + } + }, + "node_modules/dotenv-defaults/node_modules/dotenv": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/dotenv-webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/dotenv-webpack/-/dotenv-webpack-8.1.0.tgz", + "integrity": "sha512-owK1JcsPkIobeqjVrk6h7jPED/W6ZpdFsMPR+5ursB7/SdgDyO+VzAU+szK8C8u3qUhtENyYnj8eyXMR5kkGag==", + "dev": true, + "dependencies": { + "dotenv-defaults": "^2.0.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "webpack": "^4 || ^5" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.4.tgz", + "integrity": "sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA==" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/envinfo": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", + "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", + "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint": { + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.8.0.tgz", + "integrity": "sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.17.1", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.8.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.0.2", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "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" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", + "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz", + "integrity": "sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==", + "dev": true, + "dependencies": { + "aria-query": "~5.1.3", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.9.1", + "axobject-query": "~3.1.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "es-iterator-helpers": "^1.0.19", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.0" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", + "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.9.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.35.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz", + "integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.19", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-scope": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", + "dev": true, + "dependencies": { + "acorn": "^8.12.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter2": { + "version": "6.4.7", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", + "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==", + "dev": true + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/executable": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", + "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "dev": true, + "dependencies": { + "pify": "^2.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dev": true, + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extract-zip/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true, + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fast-uri": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", + "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.2.tgz", + "integrity": "sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cosmiconfig": "^8.2.0", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">=12.13.0", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "typescript": ">3.6.0", + "webpack": "^5.11.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.6.tgz", + "integrity": "sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/getos": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", + "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", + "dev": true, + "dependencies": { + "async": "^3.2.0" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "dev": true, + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals": { + "version": "15.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", + "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/graphql": { + "version": "16.9.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz", + "integrity": "sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/haengdong-design": { + "version": "0.1.81", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.81.tgz", + "integrity": "sha512-IiXkt0zXSEmn7vstTLOeNZLFS35JO8lXbXavM55wdyAJd+w0e5kfRxyDk/K2oSiAnX2c2YPiGep/A0x2/gZPDg==", + "dependencies": { + "@emotion/react": "^11.11.4", + "@storybook/addon-webpack5-compiler-swc": "^1.0.5", + "@svgr/webpack": "^8.1.0", + "lottie-react": "^2.4.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.24.1" + }, + "engines": { + "node": ">=20.15.1", + "npm": ">=10.7.0" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/headers-polyfill": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz", + "integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==", + "dev": true + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/html-loader": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-5.1.0.tgz", + "integrity": "sha512-Jb3xwDbsm0W3qlXrCZwcYqYGnYz55hb6aoKQTlzyZPXsPpi6tHXzAfqalecglMQgNvtEfxrCQPaKT90Irt5XDA==", + "dev": true, + "dependencies": { + "html-minifier-terser": "^7.2.0", + "parse5": "^7.1.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/html-minifier-terser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", + "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "~5.3.2", + "commander": "^10.0.0", + "entities": "^4.4.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.15.1" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", + "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", + "dev": true, + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/html-webpack-plugin/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/html-webpack-plugin/node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/http-signature": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", + "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2", + "sshpk": "^1.14.1" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/hyperdyperid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", + "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", + "dev": true, + "engines": { + "node": ">=10.18" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", + "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dev": true, + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-network-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", + "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", + "dev": true + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "dev": true, + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", + "dev": true, + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jake/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jake/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jake/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jake/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jake/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jake/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jake/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jake/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-canvas-mock": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jest-canvas-mock/-/jest-canvas-mock-2.5.2.tgz", + "integrity": "sha512-vgnpPupjOL6+L5oJXzxTxFrlGEIbHdZqFU+LFNdtLxZ3lRDCl17FlTMM7IatoRQkrcyOTMlDinjUguqmQ6bR2A==", + "dependencies": { + "cssfontparser": "^1.2.1", + "moo-color": "^1.0.2" + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-circus/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-circus/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-circus/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-cli/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-cli/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-config/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-config/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-config/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jest-config/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-diff/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-diff/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-each/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-each/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-each/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-jsdom": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz", + "integrity": "sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/jsdom": "^20.0.0", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0", + "jsdom": "^20.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jest-environment-jsdom/node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-jsdom/node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "node_modules/jest-environment-jsdom/node_modules/data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "dev": true, + "dependencies": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-environment-jsdom/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jest-environment-jsdom/node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-environment-jsdom/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jest-environment-jsdom/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-environment-jsdom/node_modules/jsdom": { + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", + "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", + "dev": true, + "dependencies": { + "abab": "^2.0.6", + "acorn": "^8.8.1", + "acorn-globals": "^7.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.2", + "decimal.js": "^10.4.2", + "domexception": "^4.0.0", + "escodegen": "^2.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.2", + "parse5": "^7.1.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.2", + "w3c-xmlserializer": "^4.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0", + "ws": "^8.11.0", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jest-environment-jsdom/node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dev": true, + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-environment-jsdom/node_modules/w3c-xmlserializer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", + "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", + "dev": true, + "dependencies": { + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/jest-environment-jsdom/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-environment-jsdom/node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-environment-jsdom/node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-environment-jsdom/node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dev": true, + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-environment-jsdom/node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-haste-map/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-haste-map/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-matcher-utils/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-matcher-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-message-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-message-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-resolve/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-resolve/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-resolve/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-resolve/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-resolve/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-runner/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-runner/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/jest-runner/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-runtime/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-runtime/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-runtime/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jest-runtime/node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-snapshot/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-snapshot/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-validate/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-validate/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-validate/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-watcher/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-watcher/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-watcher/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-watcher/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-watcher/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true + }, + "node_modules/jsdom": { + "version": "24.1.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.1.tgz", + "integrity": "sha512-5O1wWV99Jhq4DV7rCLIoZ/UIhyQeDR7wHVyZAHAshbrvZsLs+Xzz7gtwnlJTJDjleiTKh54F4dXrX70vJQTyJQ==", + "dev": 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.5", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.12", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.7.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.4", + "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.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^2.11.2" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jsdom/node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dev": true, + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdom/node_modules/whatwg-url": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "dev": true, + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsprim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", + "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/launch-editor": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.8.0.tgz", + "integrity": "sha512-vJranOAJrI/llyWGRQqiDM+adrw+k83fvmmx3+nV47g3+36xM15jE+zyZ6Ffel02+xSvuM0b2GDRosXZkbb6wA==", + "dev": true, + "dependencies": { + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" + } + }, + "node_modules/lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", + "dev": true, + "engines": { + "node": "> 0.8" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/listr2": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", + "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", + "dev": true, + "dependencies": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.1", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/listr2/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/listr2/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils-webpack-v4": { + "name": "loader-utils", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-update/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lottie-react": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/lottie-react/-/lottie-react-2.4.0.tgz", + "integrity": "sha512-pDJGj+AQlnlyHvOHFK7vLdsDcvbuqvwPZdMlJ360wrzGFurXeKPr8SiRCjLf3LrNYKANQtSsh5dz9UYQHuqx4w==", + "dependencies": { + "lottie-web": "^5.10.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/lottie-web": { + "version": "5.12.2", + "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz", + "integrity": "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==" + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/modify-source-webpack-plugin": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/modify-source-webpack-plugin/-/modify-source-webpack-plugin-4.1.0.tgz", + "integrity": "sha512-UaLQyFXoPWpWxkNUBFo9BotC20CCAGe7HEX9iKtB0P0MgNXgURf9TXUgNGuY5iVV5lDDQtcMjT2vneQWnNmwEw==", + "dev": true, + "dependencies": { + "loader-utils-webpack-v4": "npm:loader-utils@^2.0.4", + "schema-utils": "^4.0.0" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + } + }, + "node_modules/modify-source-webpack-plugin/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/modify-source-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/modify-source-webpack-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/modify-source-webpack-plugin/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/moo-color": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/moo-color/-/moo-color-1.0.3.tgz", + "integrity": "sha512-i/+ZKXMDf6aqYtBhuOcej71YSlbjT3wCO/4H1j8rPvxDJEifdwgg5MaFyu6iYAT8GBZJg2z0dkgK4YMzvURALQ==", + "dependencies": { + "color-name": "^1.1.4" + } + }, + "node_modules/moo-color/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/msw": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.3.5.tgz", + "integrity": "sha512-+GUI4gX5YC5Bv33epBrD+BGdmDvBg2XGruiWnI3GbIbRmMMBeZ5gs3mJ51OWSGHgJKztZ8AtZeYMMNMVrje2/Q==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@bundled-es-modules/cookie": "^2.0.0", + "@bundled-es-modules/statuses": "^1.0.1", + "@bundled-es-modules/tough-cookie": "^0.1.6", + "@inquirer/confirm": "^3.0.0", + "@mswjs/interceptors": "^0.29.0", + "@open-draft/until": "^2.1.0", + "@types/cookie": "^0.6.0", + "@types/statuses": "^2.0.4", + "chalk": "^4.1.2", + "graphql": "^16.8.1", + "headers-polyfill": "^4.0.2", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.2", + "path-to-regexp": "^6.2.0", + "strict-event-emitter": "^0.5.1", + "type-fest": "^4.9.0", + "yargs": "^17.7.2" + }, + "bin": { + "msw": "cli/index.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mswjs" + }, + "peerDependencies": { + "typescript": ">= 4.7.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/msw/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/msw/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/msw/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/msw/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/msw/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/msw/node_modules/path-to-regexp": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", + "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", + "dev": true + }, + "node_modules/msw/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dev": true, + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "dev": true + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nwsapi": { + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", + "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==", + "dev": true + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", + "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", + "dev": true, + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ospath": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", + "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", + "dev": true + }, + "node_modules/outvariant": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", + "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==", + "dev": true + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", + "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", + "dev": true, + "dependencies": { + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-copy-to-clipboard": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.1.0.tgz", + "integrity": "sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==", + "dependencies": { + "copy-to-clipboard": "^3.3.1", + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "react": "^15.3.0 || 16 || 17 || 18" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-error-boundary": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.0.13.tgz", + "integrity": "sha512-b6PwbdSv8XeOSYvjt8LpgpKrZ0yGdtZokYwkwV2wlcZbxgopHX/hgPl5VgpnoVOWd868n1hktM8Qm4b+02MiLQ==", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "peerDependencies": { + "react": ">=16.13.1" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-router": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.26.0.tgz", + "integrity": "sha512-wVQq0/iFYd3iZ9H2l3N3k4PL8EEHcb0XlU2Na8nEwmiXgIUElEH6gaJDtUQxJ+JFzmIXaQjfdpcGWaM6IoQGxg==", + "dependencies": { + "@remix-run/router": "1.19.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.26.0.tgz", + "integrity": "sha512-RRGUIiDtLrkX3uYcFiCIxKFWMcWQGMojpYZfcstc63A1+sSnVgILGIm9gNUA6na3Fm1QuPGSBQH2EMbAZOnMsQ==", + "dependencies": { + "@remix-run/router": "1.19.0", + "react-router": "6.26.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dev": true, + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/request-progress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", + "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", + "dev": true, + "dependencies": { + "throttleit": "^1.0.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true + }, + "node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "dev": true, + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rrweb-cssom": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", + "dev": true + }, + "node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dev": true, + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "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" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "dev": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/strict-event-emitter": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", + "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==", + "dev": true + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz", + "integrity": "sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + }, + "node_modules/svgo": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", + "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/svgo/node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/svgo/node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/svgo/node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/svgo/node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/swc-loader": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/swc-loader/-/swc-loader-0.2.6.tgz", + "integrity": "sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg==", + "dependencies": { + "@swc/counter": "^0.1.3" + }, + "peerDependencies": { + "@swc/core": "^1.2.147", + "webpack": ">=2" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "node_modules/synckit": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", + "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.31.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.3.tgz", + "integrity": "sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/thingies": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", + "integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==", + "dev": true, + "engines": { + "node": ">=10.18" + }, + "peerDependencies": { + "tslib": "^2" + } + }, + "node_modules/throttleit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.1.tgz", + "integrity": "sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "node_modules/tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "dev": true, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "dev": true, + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/tree-dump": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", + "integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-jest": { + "version": "29.2.4", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.4.tgz", + "integrity": "sha512-3d6tgDyhCI29HlpwIq87sNuI+3Q6GLTTCeYRHCs7vDz+/3GCMwEtV9jezLyl4ZtnBgx00I7hm8PCP8cTksMGrw==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "ejs": "^3.1.10", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-loader": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", + "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/ts-loader/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ts-loader/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ts-loader/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ts-loader/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/ts-loader/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-loader/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-loader/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/ts-loader/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.23.0.tgz", + "integrity": "sha512-ZiBujro2ohr5+Z/hZWHESLz3g08BBdrdLMieYFULJO+tWc437sn8kQsWLJoZErY8alNhxre9K4p3GURAG11n+w==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.18.0.tgz", + "integrity": "sha512-PonBkP603E3tt05lDkbOMyaxJjvKqQrXsnow72sVeOFINDE/qNmnnd+f9b4N+U7W6MXnnYyrhtmF2t08QWwUbA==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "7.18.0", + "@typescript-eslint/parser": "7.18.0", + "@typescript-eslint/utils": "7.18.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dev": true, + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/undici-types": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", + "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==", + "dev": true + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unplugin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.0.1.tgz", + "integrity": "sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==", + "dev": true, + "dependencies": { + "acorn": "^8.8.1", + "chokidar": "^3.5.3", + "webpack-sources": "^3.2.3", + "webpack-virtual-modules": "^0.5.0" + } + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", + "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/watchpack": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", + "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/webpack": { + "version": "5.93.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", + "integrity": "sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.7.1", + "acorn-import-attributes": "^1.9.5", + "browserslist": "^4.21.10", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", + "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^2.1.1", + "@webpack-cli/info": "^2.0.2", + "@webpack-cli/serve": "^2.0.5", + "colorette": "^2.0.14", + "commander": "^10.0.1", + "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-dev-middleware": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.3.0.tgz", + "integrity": "sha512-xD2qnNew+F6KwOGZR7kWdbIou/ud7cVqLEXeK1q0nHcNsX/u7ul/fSdlOTX4ntSL5FNFy7ZJJXbf0piF591JYw==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^4.6.0", + "mime-types": "^2.1.31", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/webpack-dev-middleware/node_modules/memfs": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.11.1.tgz", + "integrity": "sha512-LZcMTBAgqUUKNXZagcZxvXXfgF1bHX7Y7nQ0QyEiNbRJgE29GhgPd8Yna1VQcLlPiHt/5RFJMWYN9Uv/VPNvjQ==", + "dev": true, + "dependencies": { + "@jsonjoy.com/json-pack": "^1.0.3", + "@jsonjoy.com/util": "^1.3.0", + "tree-dump": "^1.0.1", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">= 4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + } + }, + "node_modules/webpack-dev-middleware/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-dev-server": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz", + "integrity": "sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA==", + "dev": true, + "dependencies": { + "@types/bonjour": "^3.5.13", + "@types/connect-history-api-fallback": "^1.5.4", + "@types/express": "^4.17.21", + "@types/serve-index": "^1.9.4", + "@types/serve-static": "^1.15.5", + "@types/sockjs": "^0.3.36", + "@types/ws": "^8.5.10", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.2.1", + "chokidar": "^3.6.0", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.4.0", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.1.0", + "launch-editor": "^2.6.1", + "open": "^10.0.3", + "p-retry": "^6.2.0", + "rimraf": "^5.0.5", + "schema-utils": "^4.2.0", + "selfsigned": "^2.4.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^7.1.0", + "ws": "^8.16.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-server/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/webpack-dev-server/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-virtual-modules": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz", + "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", + "dev": true + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dev": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "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" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "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 + } + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", + "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zustand": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.5.tgz", + "integrity": "sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==", + "dependencies": { + "use-sync-external-store": "1.2.2" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0.6", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } + } + } +} diff --git a/client/package.json b/client/package.json new file mode 100644 index 000000000..6d673dd06 --- /dev/null +++ b/client/package.json @@ -0,0 +1,85 @@ +{ + "name": "haengdong-client", + "version": "1.0.0", + "description": "", + "type": "module", + "scripts": { + "prod": "NODE_ENV=production webpack server --open --config webpack.prod.mjs", + "dev": "NODE_ENV=development webpack server --open --config webpack.dev.mjs", + "build": "NODE_ENV=production webpack --config webpack.prod.mjs", + "build-dev": "NODE_ENV=development webpack --config webpack.dev.mjs", + "lint": "eslint \"src/**/*.{js,jsx,ts,tsx}\"", + "format": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json,css,scss,md}'", + "cypress-open": "cypress open", + "cypress-run": "cypress run", + "test": "jest" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@eslint/compat": "^1.1.0", + "@eslint/js": "^9.6.0", + "@jest/types": "^29.6.3", + "@sentry/webpack-plugin": "^2.22.0", + "@svgr/webpack": "^8.1.0", + "@tanstack/react-query-devtools": "^5.52.0", + "@testing-library/dom": "^10.4.0", + "@testing-library/jest-dom": "^6.4.8", + "@testing-library/react": "^16.0.0", + "@types/dotenv-webpack": "^7.0.7", + "@types/jest": "^29.5.12", + "@types/react": "^18.3.3", + "@types/react-copy-to-clipboard": "^5.0.7", + "@types/react-dom": "^18.3.0", + "@types/testing-library__jest-dom": "^6.0.0", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "cypress": "^13.13.2", + "dotenv-webpack": "^8.1.0", + "eslint": "^9.6.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-jsx-a11y": "^6.9.0", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-react": "^7.34.3", + "eslint-plugin-react-hooks": "^4.6.2", + "fork-ts-checker-webpack-plugin": "^9.0.2", + "globals": "^15.8.0", + "html-loader": "^5.0.0", + "html-webpack-plugin": "^5.6.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "jsdom": "^24.1.1", + "modify-source-webpack-plugin": "^4.1.0", + "msw": "^2.3.5", + "prettier": "3.3.2", + "ts-jest": "^29.2.4", + "ts-loader": "^9.5.1", + "ts-node": "^10.9.2", + "typescript": "^5.5.4", + "typescript-eslint": "^7.16.0", + "undici": "^5.28.4", + "webpack": "^5.93.0", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^5.0.4", + "webpack-merge": "^6.0.1" + }, + "dependencies": { + "@emotion/react": "^11.11.4", + "@sentry/react": "^8.25.0", + "@tanstack/react-query": "^5.51.23", + "haengdong-design": "^0.1.81", + "jest-canvas-mock": "^2.5.2", + "react": "^18.3.1", + "react-copy-to-clipboard": "^5.1.0", + "react-dom": "^18.3.1", + "react-error-boundary": "^4.0.13", + "react-router-dom": "^6.24.1", + "zustand": "^4.5.5" + }, + "engines": { + "npm": ">=10.7.0", + "node": ">=20.15.1" + } +} diff --git a/client/public/mockServiceWorker.js b/client/public/mockServiceWorker.js new file mode 100644 index 000000000..3abd19a06 --- /dev/null +++ b/client/public/mockServiceWorker.js @@ -0,0 +1,281 @@ +/* eslint-disable */ +/* tslint:disable */ + +/** + * Mock Service Worker. + * @see https://github.com/mswjs/msw + * - Please do NOT modify this file. + * - Please do NOT serve this file on production. + */ + +const PACKAGE_VERSION = '2.3.5'; +const INTEGRITY_CHECKSUM = '26357c79639bfa20d64c0efca2a87423'; +const IS_MOCKED_RESPONSE = Symbol('isMockedResponse'); +const activeClientIds = new Set(); + +self.addEventListener('install', function () { + self.skipWaiting(); +}); + +self.addEventListener('activate', function (event) { + event.waitUntil(self.clients.claim()); +}); + +self.addEventListener('message', async function (event) { + const clientId = event.source.id; + + if (!clientId || !self.clients) { + return; + } + + const client = await self.clients.get(clientId); + + if (!client) { + return; + } + + const allClients = await self.clients.matchAll({ + type: 'window', + }); + + switch (event.data) { + case 'KEEPALIVE_REQUEST': { + sendToClient(client, { + type: 'KEEPALIVE_RESPONSE', + }); + break; + } + + case 'INTEGRITY_CHECK_REQUEST': { + sendToClient(client, { + type: 'INTEGRITY_CHECK_RESPONSE', + payload: { + packageVersion: PACKAGE_VERSION, + checksum: INTEGRITY_CHECKSUM, + }, + }); + break; + } + + case 'MOCK_ACTIVATE': { + activeClientIds.add(clientId); + + sendToClient(client, { + type: 'MOCKING_ENABLED', + payload: true, + }); + break; + } + + case 'MOCK_DEACTIVATE': { + activeClientIds.delete(clientId); + break; + } + + case 'CLIENT_CLOSED': { + activeClientIds.delete(clientId); + + const remainingClients = allClients.filter(client => { + return client.id !== clientId; + }); + + // Unregister itself when there are no more clients + if (remainingClients.length === 0) { + self.registration.unregister(); + } + + break; + } + } +}); + +self.addEventListener('fetch', function (event) { + const {request} = event; + + // Bypass navigation requests. + if (request.mode === 'navigate') { + return; + } + + // Opening the DevTools triggers the "only-if-cached" request + // that cannot be handled by the worker. Bypass such requests. + if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { + return; + } + + // Bypass all requests when there are no active clients. + // Prevents the self-unregistered worked from handling requests + // after it's been deleted (still remains active until the next reload). + if (activeClientIds.size === 0) { + return; + } + + // Generate unique request ID. + const requestId = crypto.randomUUID(); + event.respondWith(handleRequest(event, requestId)); +}); + +async function handleRequest(event, requestId) { + const client = await resolveMainClient(event); + const response = await getResponse(event, client, requestId); + + // Send back the response clone for the "response:*" life-cycle events. + // Ensure MSW is active and ready to handle the message, otherwise + // this message will pend indefinitely. + if (client && activeClientIds.has(client.id)) { + (async function () { + const responseClone = response.clone(); + + sendToClient( + client, + { + type: 'RESPONSE', + payload: { + requestId, + isMockedResponse: IS_MOCKED_RESPONSE in response, + type: responseClone.type, + status: responseClone.status, + statusText: responseClone.statusText, + body: responseClone.body, + headers: Object.fromEntries(responseClone.headers.entries()), + }, + }, + [responseClone.body], + ); + })(); + } + + return response; +} + +// Resolve the main client for the given event. +// Client that issues a request doesn't necessarily equal the client +// that registered the worker. It's with the latter the worker should +// communicate with during the response resolving phase. +async function resolveMainClient(event) { + const client = await self.clients.get(event.clientId); + + if (client?.frameType === 'top-level') { + return client; + } + + const allClients = await self.clients.matchAll({ + type: 'window', + }); + + return allClients + .filter(client => { + // Get only those clients that are currently visible. + return client.visibilityState === 'visible'; + }) + .find(client => { + // Find the client ID that's recorded in the + // set of clients that have registered the worker. + return activeClientIds.has(client.id); + }); +} + +async function getResponse(event, client, requestId) { + const {request} = event; + + // Clone the request because it might've been already used + // (i.e. its body has been read and sent to the client). + const requestClone = request.clone(); + + function passthrough() { + const headers = Object.fromEntries(requestClone.headers.entries()); + + // Remove internal MSW request header so the passthrough request + // complies with any potential CORS preflight checks on the server. + // Some servers forbid unknown request headers. + delete headers['x-msw-intention']; + + return fetch(requestClone, {headers}); + } + + // Bypass mocking when the client is not active. + if (!client) { + return passthrough(); + } + + // Bypass initial page load requests (i.e. static assets). + // The absence of the immediate/parent client in the map of the active clients + // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet + // and is not ready to handle requests. + if (!activeClientIds.has(client.id)) { + return passthrough(); + } + + // Notify the client that a request has been intercepted. + const requestBuffer = await request.arrayBuffer(); + const clientMessage = await sendToClient( + client, + { + type: 'REQUEST', + payload: { + id: requestId, + url: request.url, + mode: request.mode, + method: request.method, + headers: Object.fromEntries(request.headers.entries()), + cache: request.cache, + credentials: request.credentials, + destination: request.destination, + integrity: request.integrity, + redirect: request.redirect, + referrer: request.referrer, + referrerPolicy: request.referrerPolicy, + body: requestBuffer, + keepalive: request.keepalive, + }, + }, + [requestBuffer], + ); + + switch (clientMessage.type) { + case 'MOCK_RESPONSE': { + return respondWithMock(clientMessage.data); + } + + case 'PASSTHROUGH': { + return passthrough(); + } + } + + return passthrough(); +} + +function sendToClient(client, message, transferrables = []) { + return new Promise((resolve, reject) => { + const channel = new MessageChannel(); + + channel.port1.onmessage = event => { + if (event.data && event.data.error) { + return reject(event.data.error); + } + + resolve(event.data); + }; + + client.postMessage(message, [channel.port2].concat(transferrables.filter(Boolean))); + }); +} + +async function respondWithMock(response) { + // Setting response status code to 0 is a no-op. + // However, when responding with a "Response.error()", the produced Response + // instance will have status code set to 0. Since it's not possible to create + // a Response instance with status code 0, handle that use-case separately. + if (response.status === 0) { + return Response.error(); + } + + const mockedResponse = new Response(response.body, response); + + Reflect.defineProperty(mockedResponse, IS_MOCKED_RESPONSE, { + value: true, + enumerable: true, + }); + + return mockedResponse; +} diff --git a/client/src/App.tsx b/client/src/App.tsx new file mode 100644 index 000000000..4e9ce39e1 --- /dev/null +++ b/client/src/App.tsx @@ -0,0 +1,31 @@ +import {Outlet} from 'react-router-dom'; +import {HDesignProvider} from 'haengdong-design'; +import {Global} from '@emotion/react'; +import {ReactQueryDevtools} from '@tanstack/react-query-devtools'; + +import {ToastProvider} from '@hooks/useToast/ToastProvider'; +import QueryClientBoundary from '@components/QueryClientBoundary/QueryClientBoundary'; +import ErrorCatcher from '@components/AppErrorBoundary/ErrorCatcher'; + +import {GlobalStyle} from './GlobalStyle'; +import UnhandledErrorBoundary from './UnhandledErrorBoundary'; + +const App: React.FC = () => { + return ( + + + + + + + + + + + + + + ); +}; + +export default App; diff --git a/client/src/GlobalStyle.ts b/client/src/GlobalStyle.ts new file mode 100644 index 000000000..ab16de8e1 --- /dev/null +++ b/client/src/GlobalStyle.ts @@ -0,0 +1,160 @@ +import {css} from '@emotion/react'; + +// reset css -> index css +export const GlobalStyle = css` + html, + body, + div, + span, + applet, + object, + iframe, + h1, + h2, + h3, + h4, + h5, + h6, + p, + blockquote, + pre, + a, + abbr, + acronym, + address, + big, + cite, + code, + del, + dfn, + em, + img, + ins, + kbd, + q, + s, + samp, + small, + strike, + strong, + sub, + sup, + tt, + b, + u, + i, + center, + dl, + dt, + dd, + ol, + ul, + li, + fieldset, + form, + label, + legend, + table, + caption, + tbody, + tfoot, + thead, + tr, + th, + td, + article, + aside, + canvas, + details, + embed, + figure, + figcaption, + footer, + header, + hgroup, + menu, + nav, + output, + ruby, + section, + summary, + time, + mark, + audio, + video { + vertical-align: baseline; + margin: 0; + border: 0; + padding: 0; + font-size: 100%; + font: inherit; + } + /* HTML5 display-role reset for older browsers */ + article, + aside, + details, + figcaption, + figure, + footer, + header, + hgroup, + menu, + nav, + section { + display: block; + } + body { + line-height: 1; + } + ol, + ul { + list-style: none; + } + blockquote, + q { + quotes: none; + } + blockquote:before, + blockquote:after, + q:before, + q:after { + content: ''; + content: none; + } + table { + border-collapse: collapse; + border-spacing: 0; + } + button { + cursor: pointer; + border: none; + background-color: transparent; + } + * { + box-sizing: border-box; + } + + html { + height: 100%; + } + + body { + max-width: 768px; + height: 100%; + margin: 0 auto; + + overflow-y: scroll; + &::-webkit-scrollbar { + display: none; + } + } + + section { + width: 100%; + } + + #root { + display: flex; + flex-direction: column; + } +`; diff --git a/client/src/UnhandledErrorBoundary.tsx b/client/src/UnhandledErrorBoundary.tsx new file mode 100644 index 000000000..78d017344 --- /dev/null +++ b/client/src/UnhandledErrorBoundary.tsx @@ -0,0 +1,10 @@ +import {StrictPropsWithChildren} from 'haengdong-design/dist/type/strictPropsWithChildren'; +import {ErrorBoundary} from 'react-error-boundary'; + +import ErrorPage from '@pages/ErrorPage/ErrorPage'; + +const UnhandledErrorBoundary = ({children}: StrictPropsWithChildren) => { + return }>{children}; +}; + +export default UnhandledErrorBoundary; diff --git a/client/src/apis/baseUrl.ts b/client/src/apis/baseUrl.ts new file mode 100644 index 000000000..37fc00a94 --- /dev/null +++ b/client/src/apis/baseUrl.ts @@ -0,0 +1,3 @@ +export const BASE_URL = { + HD: process.env.API_BASE_URL, +}; diff --git a/client/src/apis/fetcher.ts b/client/src/apis/fetcher.ts new file mode 100644 index 000000000..2e1c2d067 --- /dev/null +++ b/client/src/apis/fetcher.ts @@ -0,0 +1,120 @@ +import {ErrorInfo} from '@components/AppErrorBoundary/ErrorCatcher'; + +import objectToQueryString from '@utils/objectToQueryString'; + +import {UNKNOWN_ERROR} from '@constants/errorMessage'; + +import FetchError from '../errors/FetchError'; + +export type Method = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'; + +type Body = ReadableStream | XMLHttpRequestBodyInit; +type HeadersType = [string, string][] | Record | Headers; + +export type ObjectQueryParams = Record; + +type RequestProps = { + baseUrl?: string; + endpoint: string; + headers?: HeadersType; + body?: Body | object | null; + queryParams?: ObjectQueryParams; +}; + +type FetcherProps = RequestProps & { + method: Method; +}; + +type Options = { + method: Method; + headers: HeadersType; + body?: Body | null; +}; + +type ErrorHandlerProps = { + url: string; + options: Options; + body: string; +}; + +const API_BASE_URL = process.env.API_BASE_URL ?? ''; + +export const requestGet = async ({headers = {}, ...args}: RequestProps): Promise => { + const response = await fetcher({ + ...args, + method: 'GET', + headers, + }); + + const data: T = await response!.json(); + return data; +}; + +export const requestPatch = ({headers = {}, ...args}: RequestProps) => { + return fetcher({method: 'PATCH', headers, ...args}); +}; + +export const requestPut = ({headers = {}, ...args}: RequestProps) => { + return fetcher({method: 'PUT', headers, ...args}); +}; + +export const requestPostWithoutResponse = async ({headers = {}, ...args}: RequestProps) => { + await fetcher({method: 'POST', headers, ...args}); +}; + +export const requestPostWithResponse = async ({headers = {}, ...args}: RequestProps): Promise => { + const response = await fetcher({method: 'POST', headers, ...args}); + + const data: T = await response!.json(); + return data; +}; + +export const requestDelete = ({headers = {}, ...args}: RequestProps) => { + return fetcher({method: 'DELETE', headers, ...args}); +}; + +const fetcher = ({baseUrl = API_BASE_URL, method, endpoint, headers, body, queryParams}: FetcherProps) => { + const options = { + method, + credentials: 'include', + headers: { + 'Content-Type': 'application/json', + ...headers, + }, + body: body ? JSON.stringify(body) : null, + }; + + let url = `${baseUrl}${endpoint}`; + + if (queryParams) url += `?${objectToQueryString(queryParams)}`; + + return errorHandler({url, options, body: JSON.stringify(body)}); +}; + +const errorHandler = async ({url, options, body}: ErrorHandlerProps) => { + try { + const response: Response = await fetch(url, options); + + if (!response.ok) { + const serverErrorInfo: ErrorInfo = await response.json(); + + throw new FetchError({ + status: response.status, + requestBody: body, + endpoint: response.url, + errorInfo: serverErrorInfo, + name: serverErrorInfo.errorCode, + message: serverErrorInfo.message || '', + method: options.method, + }); + } + + return response; + } catch (error) { + if (error instanceof Error) { + throw error; // ๊ทธ๋Œ€๋กœ FetchError || Error ์ธ์Šคํ„ด์Šค๋ฅผ ๋˜์ง‘๋‹ˆ๋‹ค. + } + + throw new Error(UNKNOWN_ERROR); + } +}; diff --git a/client/src/apis/request/auth.ts b/client/src/apis/request/auth.ts new file mode 100644 index 000000000..9c56d1f6b --- /dev/null +++ b/client/src/apis/request/auth.ts @@ -0,0 +1,25 @@ +import {BASE_URL} from '@apis/baseUrl'; +import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {requestPostWithoutResponse} from '@apis/fetcher'; +import {WithEventId} from '@apis/withEventId.type'; + +export type RequestToken = { + password: string; +}; + +export const requestPostAuthentication = async ({eventId}: WithEventId) => { + await requestPostWithoutResponse({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/auth`, + }); +}; + +export const requestPostToken = async ({eventId, password}: WithEventId) => { + await requestPostWithoutResponse({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/login`, + body: { + password: password, + }, + }); +}; diff --git a/client/src/apis/request/bill.ts b/client/src/apis/request/bill.ts new file mode 100644 index 000000000..c08168520 --- /dev/null +++ b/client/src/apis/request/bill.ts @@ -0,0 +1,69 @@ +import type {Bill, MemberReportInAction} from 'types/serviceType'; + +import {BASE_URL} from '@apis/baseUrl'; +import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {requestDelete, requestGet, requestPostWithoutResponse, requestPut} from '@apis/fetcher'; +import {WithEventId} from '@apis/withEventId.type'; + +type RequestPostBillList = { + billList: Bill[]; +}; + +export const requestPostBillList = async ({eventId, billList}: WithEventId) => { + await requestPostWithoutResponse({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions`, + body: { + actions: billList, + }, + }); +}; + +type RequestBillAction = { + actionId: number; +}; + +export const requestDeleteBillAction = async ({eventId, actionId}: WithEventId) => { + await requestDelete({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions/${actionId}`, + }); +}; + +type RequestPutBillAction = Bill & RequestBillAction; + +export const requestPutBillAction = async ({eventId, actionId, title, price}: WithEventId) => { + await requestPut({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions/${actionId}`, + body: { + title, + price, + }, + }); +}; + +export type MemberReportList = {members: MemberReportInAction[]}; + +export const requestGetMemberReportListInAction = async ({eventId, actionId}: WithEventId) => { + return requestGet({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions/${actionId}/fixed`, + }); +}; + +type RequestPutMemberReportList = RequestBillAction & MemberReportList; + +export const requestPutMemberReportListInAction = async ({ + eventId, + actionId, + members, +}: WithEventId) => { + return requestPut({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions/${actionId}/fixed`, + body: { + members, + }, + }); +}; diff --git a/client/src/apis/request/event.ts b/client/src/apis/request/event.ts new file mode 100644 index 000000000..c9299c813 --- /dev/null +++ b/client/src/apis/request/event.ts @@ -0,0 +1,32 @@ +import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {requestGet, requestPostWithResponse} from '@apis/fetcher'; +import {WithEventId} from '@apis/withEventId.type'; + +export type RequestPostNewEvent = { + eventName: string; + password: number; +}; + +export type ResponsePostNewEvent = { + eventId: string; +}; + +export const requestPostNewEvent = async ({eventName, password}: RequestPostNewEvent) => { + return await requestPostWithResponse({ + endpoint: TEMP_PREFIX, + body: { + eventName: eventName, + password: password, + }, + }); +}; + +type ResponseGetEventName = { + eventName: string; +}; + +export const requestGetEventName = async ({eventId}: WithEventId) => { + return requestGet({ + endpoint: `${TEMP_PREFIX}/${eventId}`, + }); +}; diff --git a/client/src/apis/request/member.ts b/client/src/apis/request/member.ts new file mode 100644 index 000000000..dd7152575 --- /dev/null +++ b/client/src/apis/request/member.ts @@ -0,0 +1,84 @@ +import type {MemberType} from 'types/serviceType'; + +import {BASE_URL} from '@apis/baseUrl'; +import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {requestDelete, requestGet, requestPut, requestPostWithoutResponse} from '@apis/fetcher'; +import {WithEventId} from '@apis/withEventId.type'; + +type RequestPostMemberList = { + memberNameList: string[]; + type: MemberType; +}; + +export const requestPostMemberList = async ({eventId, type, memberNameList}: WithEventId) => { + await requestPostWithoutResponse({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/member-actions`, + body: { + members: memberNameList, + status: type, + }, + }); +}; + +type RequestDeleteMemberAction = { + actionId: number; +}; + +export const requestDeleteMemberAction = async ({eventId, actionId}: WithEventId) => { + await requestDelete({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/member-actions/${actionId}`, + }); +}; + +type ResponseGetAllMemberList = { + memberNames: string[]; +}; + +export const requestGetAllMemberList = async ({eventId}: WithEventId) => { + return requestGet({ + endpoint: `${TEMP_PREFIX}/${eventId}/members`, + }); +}; + +export type MemberChange = { + before: string; + after: string; +}; + +type RequestPutAllMemberList = { + members: MemberChange[]; +}; + +export const requestPutAllMemberList = async ({eventId, members}: WithEventId) => { + await requestPut({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/members/nameChange`, + body: { + members, + }, + }); +}; + +type RequestDeleteAllMemberList = { + memberName: string; +}; + +export const requestDeleteAllMemberList = async ({eventId, memberName}: WithEventId) => { + await requestDelete({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/members/${memberName}`, + }); +}; + +export type ResponseGetCurrentInMemberList = { + memberNames: string[]; +}; + +export const requestGetCurrentInMemberList = async ({eventId}: WithEventId) => { + return await requestGet({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/members/current`, + }); +}; diff --git a/client/src/apis/request/report.ts b/client/src/apis/request/report.ts new file mode 100644 index 000000000..8992f9c30 --- /dev/null +++ b/client/src/apis/request/report.ts @@ -0,0 +1,19 @@ +import type {MemberReport} from 'types/serviceType'; + +import {BASE_URL} from '@apis/baseUrl'; +import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {requestGet} from '@apis/fetcher'; +import {WithEventId} from '@apis/withEventId.type'; + +type ResponseGetMemberReportList = { + reports: MemberReport[]; +}; + +export const requestGetMemberReportList = async ({eventId}: WithEventId) => { + const {reports} = await requestGet({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/actions/reports`, + }); + + return reports; +}; diff --git a/client/src/apis/request/stepList.ts b/client/src/apis/request/stepList.ts new file mode 100644 index 000000000..0d47ab90e --- /dev/null +++ b/client/src/apis/request/stepList.ts @@ -0,0 +1,17 @@ +import type {StepList} from 'types/serviceType'; + +import {BASE_URL} from '@apis/baseUrl'; +import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {requestGet} from '@apis/fetcher'; +import {WithEventId} from '@apis/withEventId.type'; + +// TODO: (@weadie) ํ˜„์žฌ ํ† ํฐ์„ ์–ด๋–ป๊ฒŒ ๊ด€๋ฆฌํ• ์ง€.. ๊ณ„์† ์‚ฌ์šฉ๋˜๋Š”๋ฐ +export const requestGetStepList = async ({eventId}: WithEventId) => { + // TODO: (@weadie) response๊ฐ€ ์–ด๋–ป๊ฒŒ ์˜ค๋Š”์ง€ ์•ˆ๋‚˜์™€์„œ data๋กœ๋งŒ ์จ๋’€์–ด์š”. + const {steps} = await requestGet({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/actions`, + }); + + return steps; +}; diff --git a/client/src/apis/tempPrefix.ts b/client/src/apis/tempPrefix.ts new file mode 100644 index 000000000..949981b73 --- /dev/null +++ b/client/src/apis/tempPrefix.ts @@ -0,0 +1,2 @@ +// TODO: (@weadie) ๋ฐ˜๋ณต๋˜์„œ ์“ฐ์ด๋Š” ์ด api/events๊ฐ€ ์ถ”ํ›„ ์ˆ˜์ • ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์–ด์„œ ์ผ๋‹จ ํŽธ์ง‘ํ•˜๊ธฐ ํŽธํ•˜๊ฒŒ ์ด ๋ณ€์ˆ˜๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค. +export const TEMP_PREFIX = '/api/events'; diff --git a/client/src/apis/withEventId.type.ts b/client/src/apis/withEventId.type.ts new file mode 100644 index 000000000..b88160e3e --- /dev/null +++ b/client/src/apis/withEventId.type.ts @@ -0,0 +1,3 @@ +export type WithEventId

= P & { + eventId: string; +}; diff --git a/client/src/assets/image/addBillMockup.svg b/client/src/assets/image/addBillMockup.svg new file mode 100644 index 000000000..c7e4aa109 --- /dev/null +++ b/client/src/assets/image/addBillMockup.svg @@ -0,0 +1,312 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/assets/image/addMemberMockup.svg b/client/src/assets/image/addMemberMockup.svg new file mode 100644 index 000000000..1bf5892d3 --- /dev/null +++ b/client/src/assets/image/addMemberMockup.svg @@ -0,0 +1,317 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/assets/image/chevronDownLarge.svg b/client/src/assets/image/chevronDownLarge.svg new file mode 100644 index 000000000..11a631f88 --- /dev/null +++ b/client/src/assets/image/chevronDownLarge.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/src/assets/image/dog.svg b/client/src/assets/image/dog.svg new file mode 100644 index 000000000..f70558ed6 --- /dev/null +++ b/client/src/assets/image/dog.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/assets/image/heundeut.svg b/client/src/assets/image/heundeut.svg new file mode 100644 index 000000000..c78ca8c9b --- /dev/null +++ b/client/src/assets/image/heundeut.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/src/assets/image/memberReportMockup.svg b/client/src/assets/image/memberReportMockup.svg new file mode 100644 index 000000000..efbaf3c1c --- /dev/null +++ b/client/src/assets/image/memberReportMockup.svg @@ -0,0 +1,311 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/assets/image/runningDog.svg b/client/src/assets/image/runningDog.svg new file mode 100644 index 000000000..60951e642 --- /dev/null +++ b/client/src/assets/image/runningDog.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/client/src/assets/image/standingDog.svg b/client/src/assets/image/standingDog.svg new file mode 100644 index 000000000..2d34a8cf9 --- /dev/null +++ b/client/src/assets/image/standingDog.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx b/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx new file mode 100644 index 000000000..8d7946b8a --- /dev/null +++ b/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx @@ -0,0 +1,92 @@ +import {render, screen, waitFor} from '@testing-library/react'; +import {act, ReactNode} from 'react'; +import {MemoryRouter} from 'react-router-dom'; +import {HDesignProvider} from 'haengdong-design'; + +import FetchError from '@errors/FetchError'; +import {ToastProvider} from '@hooks/useToast/ToastProvider'; + +import {useAppErrorStore} from '@store/appErrorStore'; + +import {SERVER_ERROR_MESSAGES} from '@constants/errorMessage'; + +import UnhandledErrorBoundary from '../../UnhandledErrorBoundary'; + +import ErrorCatcher from './ErrorCatcher'; + +// ํ…Œ์ŠคํŠธ์šฉ ํ—ฌํผ ์ปดํฌ๋„ŒํŠธ +const TestComponent = ({triggerError}: {triggerError: () => void}) => { + return ; +}; + +const setup = (ui: ReactNode) => + render( + + + + + {ui} + + + + , + ); + +describe('ErrorCatcher', () => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useNavigate: jest.fn(), + })); + + it('ํ•ธ๋“ค๋ง ๊ฐ€๋Šฅํ•œ ์—๋Ÿฌ์ธ ๊ฒฝ์šฐ ํ† ์ŠคํŠธ๊ฐ€ ํ‘œ์‹œ๋œ๋‹ค.', async () => { + const errorCode = 'EVENT_NOT_FOUND'; + const error = new FetchError({ + errorInfo: {errorCode, message: '์„œ๋ฒ„์˜ ์—๋Ÿฌ๋ฉ”์„ธ์ง€'}, + name: errorCode, + message: '์—๋Ÿฌ๋ฉ”์„ธ์ง€', + status: 200, + endpoint: '', + method: 'GET', + requestBody: '', + }); + + const {updateAppError} = useAppErrorStore.getState(); + + setup( updateAppError(error)} />); + + act(() => { + screen.getByText('Trigger Error').click(); + }); + + const errorMessage = SERVER_ERROR_MESSAGES[errorCode]; + + await waitFor(() => { + expect(screen.getByText(errorMessage)).toBeInTheDocument(); + }); + }); + + it('ํ•ธ๋“ค๋ง ๋ถˆ๊ฐ€๋Šฅํ•œ ์—๋Ÿฌ์ธ ๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฐ”์šด๋”๋ฆฌ๊ฐ€ ํ‘œ์‹œ๋œ๋‹ค.', async () => { + const errorCode = '๋ชจ๋ฅด๊ฒ ๋Š” ์—๋Ÿฌ'; + const error = new FetchError({ + errorInfo: {errorCode, message: '๋ชจ๋ฅด๊ฒ ๋Š” ์—๋Ÿฌ๋ฉ”์„ธ์ง€'}, + name: errorCode, + message: '์—๋Ÿฌ๋ฉ”์„ธ์ง€', + status: 400, + endpoint: '', + method: 'GET', + requestBody: '', + }); + + const {updateAppError} = useAppErrorStore.getState(); + + setup( updateAppError(error)} />); + + act(() => { + screen.getByText('Trigger Error').click(); + }); + + await waitFor(() => { + expect(screen.getByText('์•Œ ์ˆ˜ ์—†๋Š” ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค.')).toBeInTheDocument(); + }); + }); +}); diff --git a/client/src/components/AppErrorBoundary/ErrorCatcher.tsx b/client/src/components/AppErrorBoundary/ErrorCatcher.tsx new file mode 100644 index 000000000..dde5f3d64 --- /dev/null +++ b/client/src/components/AppErrorBoundary/ErrorCatcher.tsx @@ -0,0 +1,62 @@ +import {useEffect} from 'react'; + +import FetchError from '@errors/FetchError'; +import {useToast} from '@hooks/useToast/useToast'; + +import {useAppErrorStore} from '@store/appErrorStore'; + +import {captureError} from '@utils/captureError'; + +import {SERVER_ERROR_MESSAGES, UNKNOWN_ERROR} from '@constants/errorMessage'; + +export type ErrorInfo = { + errorCode: string; + message: string; +}; + +const convertAppErrorToErrorInfo = (appError: Error) => { + if (appError instanceof Error) { + const errorInfo = + appError instanceof FetchError ? appError.errorInfo : {errorCode: appError.name, message: appError.message}; + + return errorInfo; + } else { + const errorInfo = {errorCode: UNKNOWN_ERROR, message: JSON.stringify(appError)}; + + return errorInfo; + } +}; + +const isUnhandledError = (errorInfo: ErrorInfo) => { + if (errorInfo.errorCode === 'INTERNAL_SERVER_ERROR') return true; + + return SERVER_ERROR_MESSAGES[errorInfo.errorCode] === undefined; +}; + +const ErrorCatcher = ({children}: React.PropsWithChildren) => { + const {appError} = useAppErrorStore(); + const {showToast} = useToast(); + + useEffect(() => { + if (appError) { + const errorInfo = convertAppErrorToErrorInfo(appError); + captureError(appError, errorInfo); + + if (!isUnhandledError(errorInfo)) { + showToast({ + showingTime: 3000, + message: SERVER_ERROR_MESSAGES[errorInfo.errorCode], + type: 'error', + position: 'bottom', + bottom: '8rem', + }); + } else { + throw appError; + } + } + }, [appError]); + + return children; +}; + +export default ErrorCatcher; diff --git a/client/src/components/Common/Logo/Logo.style.ts b/client/src/components/Common/Logo/Logo.style.ts new file mode 100644 index 000000000..89f97ede0 --- /dev/null +++ b/client/src/components/Common/Logo/Logo.style.ts @@ -0,0 +1,8 @@ +import {css} from '@emotion/react'; + +export const logoStyle = css({ + display: 'flex', + justifyContent: 'center', + + width: '100%', +}); diff --git a/client/src/components/Common/Logo/RunningDogLogo.tsx b/client/src/components/Common/Logo/RunningDogLogo.tsx new file mode 100644 index 000000000..a09a904c1 --- /dev/null +++ b/client/src/components/Common/Logo/RunningDogLogo.tsx @@ -0,0 +1,13 @@ +import RunningDog from '@assets/image/runningDog.svg'; + +import {logoStyle} from './Logo.style'; + +const RunningDogLogo = () => { + return ( +

+ +
+ ); +}; + +export default RunningDogLogo; diff --git a/client/src/components/Common/Logo/StandingDogLogo.tsx b/client/src/components/Common/Logo/StandingDogLogo.tsx new file mode 100644 index 000000000..5c2cf591e --- /dev/null +++ b/client/src/components/Common/Logo/StandingDogLogo.tsx @@ -0,0 +1,13 @@ +import StandingDog from '@assets/image/standingDog.svg'; + +import {logoStyle} from './Logo.style'; + +const StandingDogLogo = () => { + return ( +
+ +
+ ); +}; + +export default StandingDogLogo; diff --git a/client/src/components/Common/Logo/index.ts b/client/src/components/Common/Logo/index.ts new file mode 100644 index 000000000..43a08fd54 --- /dev/null +++ b/client/src/components/Common/Logo/index.ts @@ -0,0 +1,2 @@ +export {default as StandingDog} from './StandingDogLogo'; +export {default as RunningDog} from './RunningDogLogo'; diff --git a/client/src/components/MemberReportList/MemberReportList.tsx b/client/src/components/MemberReportList/MemberReportList.tsx new file mode 100644 index 000000000..1004540fa --- /dev/null +++ b/client/src/components/MemberReportList/MemberReportList.tsx @@ -0,0 +1,22 @@ +import {ExpenseList, Flex, Input} from 'haengdong-design'; +import React, {useState} from 'react'; + +import useSearchMemberReportList from '@hooks/useSearchMemberReportList/useSearchMemberReportList'; + +const MemberReportList = () => { + const [name, setName] = useState(''); + const {memberReportSearchList} = useSearchMemberReportList({name}); + + const changeName = ({target}: React.ChangeEvent) => { + setName(target.value); + }; + + return ( + + + + + ); +}; + +export default MemberReportList; diff --git a/client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx b/client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx new file mode 100644 index 000000000..645acb468 --- /dev/null +++ b/client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx @@ -0,0 +1,142 @@ +import type {BillAction} from 'types/serviceType'; + +import {BottomSheet, EditableItem, FixedButton, Flex, Text} from 'haengdong-design'; + +import validatePurchase from '@utils/validate/validatePurchase'; +import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; +import useMemberReportListInAction from '@hooks/useMemberReportListInAction/useMemberReportListInAction'; +import useMemberReportInput from '@hooks/useMemberReportListInAction/useMemberReportInput'; + +import usePutAndDeleteBillAction from '@hooks/usePutAndDeleteBillAction'; + +import { + bottomSheetHeaderStyle, + bottomSheetStyle, + inputContainerStyle, +} from '../SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style'; + +type PutAndDeleteBillActionModalProps = { + billAction: BillAction; + isBottomSheetOpened: boolean; + setIsBottomSheetOpened: React.Dispatch>; +}; + +const ExpenseDetailModal = ({ + billAction, + isBottomSheetOpened, + setIsBottomSheetOpened, +}: PutAndDeleteBillActionModalProps) => { + const { + inputPair, + handleInputChange, + // handleOnBlur, + // errorMessage, + // errorInfo, + canSubmit, + onDelete, + onSubmit: putBillAction, + } = usePutAndDeleteBillAction( + {title: billAction.name, price: String(billAction.price), index: 0}, + validatePurchase, + () => setIsBottomSheetOpened(false), + ); + + const { + memberReportListInAction, + addAdjustedMember, + onSubmit: putMemberReportListInAction, + getIsSamePriceStateAndServerState, + getOnlyOneNotAdjustedRemainMemberIndex, + isExistAdjustedPrice, + } = useMemberReportListInAction(billAction.actionId, Number(inputPair.price), () => setIsBottomSheetOpened(false)); + const { + inputList, + onChange, + canEditList, + canSubmit: isChangedMemberReportInput, + } = useMemberReportInput({ + data: memberReportListInAction, + addAdjustedMember, + totalPrice: Number(inputPair.price), + getIsSamePriceStateAndServerState, + getOnlyOneNotAdjustedRemainMemberIndex, + }); + + const {data: stepListData = []} = useRequestGetStepList(); + + const actionMemberList = stepListData.filter(({actions}) => + actions.find(({actionId}) => actionId === billAction.actionId), + )[0].members; + + return ( + setIsBottomSheetOpened(false)}> +
setIsBottomSheetOpened(false)}> +

+ ์ง€์ถœ ๋‚ด์—ญ ์ƒ์„ธ +

+
+ + ) => handleInputChange('title', event)} + disabled + /> + + ) => handleInputChange('price', event)} + isFixed={isExistAdjustedPrice()} + disabled + /> + ์› + + + + + + {inputList.map(({name, price, isFixed}, index) => ( + + + + onChange(event, index)} + isFixed={isFixed} + textSize="smallBody" + value={price} + placeholder="0" + type="number" + disabled + style={{textAlign: 'right'}} + > + ์› + + + ))} + + +
+ + ๋‹ซ๊ธฐ + +
+
+ ); +}; + +export default ExpenseDetailModal; diff --git a/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.style.ts b/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.style.ts new file mode 100644 index 000000000..4bbefdba9 --- /dev/null +++ b/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.style.ts @@ -0,0 +1,10 @@ +import {css} from '@emotion/react'; + +export const bottomSheetStyle = css({ + display: 'flex', + flexDirection: 'column', + gap: '1.5rem', + width: '100%', + height: '100%', + padding: '0 1.5rem', +}); diff --git a/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx b/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx new file mode 100644 index 000000000..e3579ab6b --- /dev/null +++ b/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx @@ -0,0 +1,53 @@ +import type {MemberReport} from 'types/serviceType'; + +import {BottomSheet, FixedButton, Flex, Text} from 'haengdong-design'; + +import {bottomSheetStyle} from './MemberListInBillStep.style'; + +type MemberListInBillStepProps = { + stepName: string; + memberList: MemberReport[]; + isOpenBottomSheet: boolean; + setIsOpenBottomSheet: React.Dispatch>; +}; + +const MemberListInBillStep = ({ + stepName, + memberList, + isOpenBottomSheet, + setIsOpenBottomSheet, +}: MemberListInBillStepProps) => { + const closeModal = () => setIsOpenBottomSheet(false); + + return ( + +
+ + {`${stepName} ์ฐธ์„์ž`} + {`์ด ${memberList.length}๋ช…`} + + +
    + {memberList.map(member => ( +
  • + + + {member.name} + + + {`${member.price.toLocaleString('ko-kr')} ์›`} + + +
  • + ))} +
+
+
+ + ๋‹ซ๊ธฐ + +
+ ); +}; + +export default MemberListInBillStep; diff --git a/client/src/components/Modal/MemberListInBillStep/index.ts b/client/src/components/Modal/MemberListInBillStep/index.ts new file mode 100644 index 000000000..137df8c87 --- /dev/null +++ b/client/src/components/Modal/MemberListInBillStep/index.ts @@ -0,0 +1 @@ +export {default as MemberListInBillStep} from './MemberListInBillStep'; diff --git a/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx b/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx new file mode 100644 index 000000000..51e33589b --- /dev/null +++ b/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx @@ -0,0 +1,39 @@ +import {SetAllMemberListModal, SetInitialMemberListModal, SetActionListModal} from '@components/Modal/index'; + +interface ModalBasedOnMemberCountProps { + allMemberList: string[]; + isOpenBottomSheet: boolean; + isOpenAllMemberListButton: boolean; + setIsOpenBottomSheet: React.Dispatch>; + setIsOpenAllMemberListButton: React.Dispatch>; +} + +const ModalBasedOnMemberCount = ({ + allMemberList, + isOpenBottomSheet, + isOpenAllMemberListButton, + setIsOpenBottomSheet, + setIsOpenAllMemberListButton, +}: ModalBasedOnMemberCountProps) => { + if (isOpenAllMemberListButton) { + return ( + + ); + } + switch (allMemberList.length) { + case 0: + return ( + + ); + + default: + return ; + } +}; + +export default ModalBasedOnMemberCount; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts new file mode 100644 index 000000000..7fad2e001 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts @@ -0,0 +1,23 @@ +import {css} from '@emotion/react'; + +const container = css({ + display: 'flex', + flexDirection: 'column', + gap: '1.5rem', + height: '100%', +}); + +const inputGroup = css({ + display: 'flex', + flexDirection: 'column', + gap: '1rem', + overflow: 'auto', + paddingBottom: '14rem', +}); + +const addMemberActionListModalContentStyle = { + container, + inputGroup, +}; + +export default addMemberActionListModalContentStyle; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx new file mode 100644 index 000000000..ad6e63f28 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx @@ -0,0 +1,50 @@ +import type {MemberType} from 'types/serviceType'; + +import {FixedButton, LabelGroupInput} from 'haengdong-design'; + +import validateMemberName from '@utils/validate/validateMemberName'; +import useRequestPostMemberList from '@hooks/queries/useRequestPostMemberList'; + +import useDynamicInput from '@hooks/useDynamicInput'; + +import style from './AddMemberActionListModalContent.style'; +import InMember from './InMember'; +import OutMember from './OutMember'; + +interface AddMemberActionListModalContentProps { + inOutAction: MemberType; + setIsOpenBottomSheet: React.Dispatch>; +} + +const AddMemberActionListModalContent = ({inOutAction, setIsOpenBottomSheet}: AddMemberActionListModalContentProps) => { + const dynamicProps = useDynamicInput(validateMemberName); + const {inputList, getFilledInputList, errorMessage, canSubmit, resetInputValue} = dynamicProps; + + const {mutate: postMemberList} = useRequestPostMemberList(); + + const handleUpdateMemberListSubmit = () => { + postMemberList({memberNameList: getFilledInputList().map(({value}) => value), type: inOutAction}); + setIsOpenBottomSheet(false); + }; + + return ( +
+
+ + {inOutAction === 'IN' ? : } + +
+ { + handleUpdateMemberListSubmit(); + resetInputValue(); + }} + /> +
+ ); +}; + +export default AddMemberActionListModalContent; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx new file mode 100644 index 000000000..5f9f9a2e0 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx @@ -0,0 +1,35 @@ +import {LabelGroupInput} from 'haengdong-design'; + +import {ReturnUseDynamicInput} from '@hooks/useDynamicInput'; + +interface InMemberProps { + dynamicProps: ReturnUseDynamicInput; +} + +const InMember = ({dynamicProps}: InMemberProps) => { + const { + inputList, + inputRefList, + handleInputChange, + deleteEmptyInputElementOnBlur, + focusNextInputOnEnter, + errorIndexList, + } = dynamicProps; + return inputList.map(({value, index}) => ( + (inputRefList.current[index] = el)} + isError={errorIndexList.includes(index)} + onChange={e => handleInputChange(index, e)} + onBlur={() => deleteEmptyInputElementOnBlur()} + onKeyDown={e => focusNextInputOnEnter(e, index)} + placeholder="์ด๋ฆ„" + autoFocus={inputList.length === 1 && index === 0} + /> + )); +}; + +export default InMember; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx new file mode 100644 index 000000000..9294b18ae --- /dev/null +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx @@ -0,0 +1,52 @@ +import {LabelGroupInput, Search} from 'haengdong-design'; + +import {ReturnUseDynamicInput} from '@hooks/useDynamicInput'; +import useSearchInMemberList from '@hooks/useSearchInMemberList'; + +interface OutMemberProps { + dynamicProps: ReturnUseDynamicInput; +} + +const OutMember = ({dynamicProps}: OutMemberProps) => { + const { + inputList, + inputRefList, + errorIndexList, + deleteEmptyInputElementOnBlur, + focusNextInputOnEnter, + handleInputChange, + handleChange, + } = dynamicProps; + const {currentInputIndex, filteredInMemberList, handleCurrentInputIndex, searchCurrentInMember, chooseMember} = + useSearchInMemberList(handleChange); + + const validationAndSearchOnChange = (inputIndex: number, event: React.ChangeEvent) => { + handleCurrentInputIndex(inputIndex); + handleInputChange(inputIndex, event); + searchCurrentInMember(event); + }; + + return inputList.map(({value, index}) => ( + chooseMember(currentInputIndex, term)} + > + (inputRefList.current[index] = el)} + isError={errorIndexList.includes(index)} + onChange={e => validationAndSearchOnChange(index, e)} + onBlur={() => deleteEmptyInputElementOnBlur()} + onKeyDown={e => focusNextInputOnEnter(e, index)} + placeholder="์ด๋ฆ„" + autoFocus={inputList.length === 1 && index === 0} + /> + + )); +}; + +export default OutMember; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/index.ts b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/index.ts new file mode 100644 index 000000000..6519283f4 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/index.ts @@ -0,0 +1 @@ +export {default as AddMemberActionListModalContent} from './AddMemberActionListModalContent'; diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts new file mode 100644 index 000000000..7be2f2141 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts @@ -0,0 +1,27 @@ +import {css} from '@emotion/react'; + +export const bottomSheetStyle = css({ + display: 'flex', + flexDirection: 'column', + gap: '1.5rem', + width: '100%', + height: '100%', + padding: '0 1rem', +}); + +export const bottomSheetHeaderStyle = css({ + display: 'flex', + justifyContent: 'space-between', + alignContent: 'center', + + width: '100%', + padding: '0 0.5rem', +}); + +export const inputGroupStyle = css({ + display: 'flex', + flexDirection: 'column', + gap: '1rem', + overflow: 'auto', + paddingBottom: '11rem', +}); diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx new file mode 100644 index 000000000..04242fad1 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx @@ -0,0 +1,88 @@ +import type {MemberAction, MemberType} from 'types/serviceType'; + +import {BottomSheet, Flex, Input, Text, IconButton, FixedButton, Icon} from 'haengdong-design'; + +import useDeleteMemberAction from '@hooks/useDeleteMemberAction/useDeleteMemberAction'; +import {useToast} from '@hooks/useToast/useToast'; + +import {bottomSheetHeaderStyle, bottomSheetStyle, inputGroupStyle} from './DeleteMemberActionModal.style'; + +type DeleteMemberActionModalProps = { + memberActionType: MemberType; + memberActionList: MemberAction[]; + isBottomSheetOpened: boolean; + setIsBottomSheetOpened: React.Dispatch>; +}; + +const DeleteMemberActionModal = ({ + memberActionType, + memberActionList, + isBottomSheetOpened, + setIsBottomSheetOpened, +}: DeleteMemberActionModalProps) => { + const {showToast} = useToast(); + + const showToastAlreadyExistMemberAction = () => { + showToast({ + isClickToClose: true, + showingTime: 3000, + message: '์ด๋ฏธ ์‚ญ์ œ๋œ ์ธ์›์ž…๋‹ˆ๋‹ค.', + type: 'error', + bottom: '160px', + }); + }; + + const showToastExistSameMemberFromAfterStep = (name: string) => { + showToast({ + isClickToClose: true, + showingTime: 3000, + message: `์ดํ›„์˜ ${name}๊ฐ€ ์‚ฌ๋ผ์ ธ์š”`, + type: 'error', + position: 'top', + top: '30px', + style: { + zIndex: 9000, + }, + }); + }; + + const {aliveActionList, deleteMemberActionList, addDeleteMemberAction} = useDeleteMemberAction({ + memberActionList, + setIsBottomSheetOpened, + showToastAlreadyExistMemberAction, + showToastExistSameMemberFromAfterStep, + }); + + return ( + setIsBottomSheetOpened(false)}> +
+
+ {memberActionType === 'IN' ? '๋“ค์–ด์˜จ' : '๋‚˜๊ฐ„'} ์ธ์› ์ˆ˜์ •ํ•˜๊ธฐ + {`${aliveActionList.length}๋ช…`} +
+
    + {aliveActionList.map(member => ( +
  • + +
    + +
    + addDeleteMemberAction(member)}> + + +
    +
  • + ))} +
+ +
+
+ ); +}; + +export default DeleteMemberActionModal; diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/index.ts b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/index.ts new file mode 100644 index 000000000..2a6b52b45 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/index.ts @@ -0,0 +1 @@ +export {default as DeleteMemberActionModal} from './DeleteMemberActionModal'; diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx new file mode 100644 index 000000000..5f7d4501e --- /dev/null +++ b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx @@ -0,0 +1,149 @@ +import type {BillAction} from 'types/serviceType'; + +import {BottomSheet, EditableItem, FixedButton, Flex, Text} from 'haengdong-design'; + +import validatePurchase from '@utils/validate/validatePurchase'; +import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; +import useMemberReportListInAction from '@hooks/useMemberReportListInAction/useMemberReportListInAction'; +import useMemberReportInput from '@hooks/useMemberReportListInAction/useMemberReportInput'; + +import usePutAndDeleteBillAction from '@hooks/usePutAndDeleteBillAction'; + +import {bottomSheetHeaderStyle, bottomSheetStyle, inputContainerStyle} from './PutAndDeltetBillActionModal.style'; + +type PutAndDeleteBillActionModalProps = { + billAction: BillAction; + isBottomSheetOpened: boolean; + setIsBottomSheetOpened: React.Dispatch>; +}; + +const PutAndDeleteBillActionModal = ({ + billAction, + isBottomSheetOpened, + setIsBottomSheetOpened, +}: PutAndDeleteBillActionModalProps) => { + const { + inputPair, + handleInputChange, + // handleOnBlur, + // errorMessage, + // errorInfo, + canSubmit, + onDelete, + onSubmit: putBillAction, + } = usePutAndDeleteBillAction( + {title: billAction.name, price: String(billAction.price), index: 0}, + validatePurchase, + () => setIsBottomSheetOpened(false), + ); + + const { + memberReportListInAction, + addAdjustedMember, + onSubmit: putMemberReportListInAction, + getIsSamePriceStateAndServerState, + getOnlyOneNotAdjustedRemainMemberIndex, + isExistAdjustedPrice, + } = useMemberReportListInAction(billAction.actionId, Number(inputPair.price), () => setIsBottomSheetOpened(false)); + const { + inputList, + onChange, + canEditList, + canSubmit: isChangedMemberReportInput, + } = useMemberReportInput({ + data: memberReportListInAction, + addAdjustedMember, + totalPrice: Number(inputPair.price), + getIsSamePriceStateAndServerState, + getOnlyOneNotAdjustedRemainMemberIndex, + }); + + const {data: stepListData = []} = useRequestGetStepList(); + + const actionMemberList = stepListData.filter(({actions}) => + actions.find(({actionId}) => actionId === billAction.actionId), + )[0].members; + + return ( + setIsBottomSheetOpened(false)}> +
{ + event.preventDefault(); + + if (canSubmit) await putBillAction(event, inputPair, billAction.actionId); + if (isChangedMemberReportInput) putMemberReportListInAction(); + }} + > +

+ ์ง€์ถœ ๋‚ด์—ญ ์ˆ˜์ •ํ•˜๊ธฐ +

+
+ + ) => handleInputChange('title', event)} + /> + + ) => handleInputChange('price', event)} + isFixed={isExistAdjustedPrice()} + /> + ์› + + + + + + {inputList.map(({name, price, isFixed}, index) => ( + + + + onChange(event, index)} + isFixed={isFixed} + textSize="smallBody" + value={price} + placeholder="0" + type="number" + readOnly={!canEditList[index]} + style={{textAlign: 'right'}} + > + ์› + + + ))} + + +
+ onDelete(billAction.actionId)} + > + ์ˆ˜์ • ์™„๋ฃŒ + +
+
+ ); +}; + +export default PutAndDeleteBillActionModal; diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style.ts b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style.ts new file mode 100644 index 000000000..f58f43425 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style.ts @@ -0,0 +1,28 @@ +import {css} from '@emotion/react'; + +export const bottomSheetStyle = css({ + display: 'flex', + flexDirection: 'column', + gap: '1.5rem', + width: '100%', + height: '100%', + padding: '0 1rem', +}); + +export const bottomSheetHeaderStyle = css({ + display: 'flex', + justifyContent: 'space-between', + alignContent: 'center', + + width: '100%', + padding: '0 0.5rem', +}); + +export const inputContainerStyle = css({ + display: 'flex', + height: '100%', + flexDirection: 'column', + gap: '1.5rem', + overflow: 'auto', + paddingBottom: '14rem', +}); diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/index.ts b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/index.ts new file mode 100644 index 000000000..c7cbcfcb6 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/index.ts @@ -0,0 +1 @@ +export {default as PutAndDeleteBillActionModal} from './PutAndDeleteBillActionModal'; diff --git a/client/src/components/Modal/SetActionModal/SetActionListModal.style.ts b/client/src/components/Modal/SetActionModal/SetActionListModal.style.ts new file mode 100644 index 000000000..ca6703309 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/SetActionListModal.style.ts @@ -0,0 +1,20 @@ +import {css} from '@emotion/react'; + +export const container = css({ + display: 'flex', + flexDirection: 'column', + width: '100%', + height: '100%', + padding: '0 1.5rem', + gap: '1.5rem', +}); + +export const switchContainer = css({ + display: 'flex', + width: '100%', + justifyContent: 'space-between', +}); + +const setActionListModalStyle = {container, switchContainer}; + +export default setActionListModalStyle; diff --git a/client/src/components/Modal/SetActionModal/SetActionListModal.tsx b/client/src/components/Modal/SetActionModal/SetActionListModal.tsx new file mode 100644 index 000000000..862bd91e3 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/SetActionListModal.tsx @@ -0,0 +1,42 @@ +import type {InOutType} from 'types/serviceType'; + +import {useState} from 'react'; +import {BottomSheet, Switch, Text} from 'haengdong-design'; + +import {AddMemberActionListModalContent} from './AddMemberActionListModalContent'; +import style from './SetActionListModal.style'; + +export type ActionType = '์ง€์ถœ' | '์ธ์›'; + +interface SetActionModalContentProps { + isOpenBottomSheet: boolean; + setIsOpenBottomSheet: React.Dispatch>; +} + +const SetActionListModal = ({isOpenBottomSheet, setIsOpenBottomSheet}: SetActionModalContentProps) => { + const [inOutAction, setInOutAction] = useState('ํƒˆ์ฃผ'); + + const handleParticipantTypeChange = (value: string) => { + setInOutAction(value as InOutType); + }; + + return ( + setIsOpenBottomSheet(false)}> +
+
+ + ์ธ์› ๋ณ€๋™ + + +
+ + +
+
+ ); +}; + +export default SetActionListModal; diff --git a/client/src/components/Modal/SetActionModal/index.ts b/client/src/components/Modal/SetActionModal/index.ts new file mode 100644 index 000000000..f689cb596 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/index.ts @@ -0,0 +1 @@ +export {default as SetActionListModal} from './SetActionListModal'; diff --git a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts new file mode 100644 index 000000000..f54166c08 --- /dev/null +++ b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts @@ -0,0 +1,36 @@ +import {css} from '@emotion/react'; + +export const allMemberListModalStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + gap: '1rem', + width: '100%', + height: '100%', + }); + +export const allMemberListModalTitleStyle = () => + css({ + display: 'flex', + justifyContent: 'space-between', + width: '100%', + padding: '0 1.5rem', + }); + +export const allMemberListModalLabelGroupInputStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + padding: '0 1rem', + paddingBottom: '10rem', + + overflow: 'auto', + }); + +export const InputAndDeleteButtonContainer = () => + css({ + display: 'flex', + alignItems: 'center', + width: '100%', + gap: '1rem', + }); diff --git a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx new file mode 100644 index 000000000..58e86b917 --- /dev/null +++ b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx @@ -0,0 +1,80 @@ +import {BottomSheet, Text, LabelGroupInput, FixedButton, IconButton, Icon} from 'haengdong-design'; + +import validateMemberName from '@utils/validate/validateMemberName'; + +import useSetAllMemberList from '@hooks/useSetAllMemberList'; + +import { + allMemberListModalLabelGroupInputStyle, + allMemberListModalStyle, + allMemberListModalTitleStyle, + InputAndDeleteButtonContainer, +} from './SetAllMemberListModal.style'; + +interface SetAllMemberListModalProps { + isOpenBottomSheet: boolean; + allMemberList: string[]; + setIsOpenBottomSheet: React.Dispatch>; + setIsOpenAllMemberListButton: React.Dispatch>; +} + +const SetAllMemberListModal = ({ + isOpenBottomSheet, + allMemberList, + setIsOpenBottomSheet, + setIsOpenAllMemberListButton, +}: SetAllMemberListModalProps) => { + const handleCloseAllMemberListModal = () => { + setIsOpenAllMemberListButton(prev => !prev); + setIsOpenBottomSheet(false); + }; + + const { + editedAllMemberList, + canSubmit, + errorMessage, + errorIndexList, + handleNameChange, + handleClickDeleteButton, + handlePutAllMemberList, + } = useSetAllMemberList({ + validateFunc: validateMemberName, + allMemberList, + handleCloseAllMemberListModal, + }); + + return ( + +
+
+ ์ „์ฒด ์ฐธ์—ฌ์ž ์ˆ˜์ •ํ•˜๊ธฐ + + ์ด {allMemberList.length}๋ช… + +
+
+ + {editedAllMemberList.map((member, index) => ( +
+
+ handleNameChange(index, e)} + /> +
+ handleClickDeleteButton(index)}> + + +
+ ))} +
+
+ +
+
+ ); +}; + +export default SetAllMemberListModal; diff --git a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.style.ts b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.style.ts new file mode 100644 index 000000000..ed835682c --- /dev/null +++ b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.style.ts @@ -0,0 +1,20 @@ +import {css} from '@emotion/react'; + +export const setInitialMemberListModalStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + gap: '1.5rem', + width: '100%', + height: '100%', + padding: '0 1.5rem', + }); + +export const setInitialMemberListModalInputGroupStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + gap: '1rem', + overflow: 'auto', + paddingBottom: '11rem', + }); diff --git a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx new file mode 100644 index 000000000..f73f2616d --- /dev/null +++ b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx @@ -0,0 +1,66 @@ +import {Text, BottomSheet, FixedButton, LabelGroupInput} from 'haengdong-design'; + +import validateMemberName from '@utils/validate/validateMemberName'; +import useRequestPostMemberList from '@hooks/queries/useRequestPostMemberList'; + +import useDynamicInput from '@hooks/useDynamicInput'; + +import { + setInitialMemberListModalInputGroupStyle, + setInitialMemberListModalStyle, +} from './SetInitialMemberListModal.style'; + +interface SetInitialMemberListProps { + isOpenBottomSheet: boolean; + setIsOpenBottomSheet: React.Dispatch>; +} + +const SetInitialMemberListModal = ({isOpenBottomSheet, setIsOpenBottomSheet}: SetInitialMemberListProps) => { + const { + inputList, + inputRefList, + handleInputChange, + deleteEmptyInputElementOnBlur, + getFilledInputList, + errorMessage, + canSubmit, + errorIndexList, + focusNextInputOnEnter, + } = useDynamicInput(validateMemberName); + const {mutate: postMemberList} = useRequestPostMemberList(); + + const handleSubmit = () => { + postMemberList({memberNameList: getFilledInputList().map(({value}) => value), type: 'IN'}); + setIsOpenBottomSheet(false); + }; + + return ( + setIsOpenBottomSheet(false)}> +
+ ์‹œ์ž‘ ์ธ์› ์ถ”๊ฐ€ํ•˜๊ธฐ +
+ + {inputList.map(({value, index}) => ( + (inputRefList.current[index] = el)} + onChange={e => handleInputChange(index, e)} + onBlur={() => deleteEmptyInputElementOnBlur()} + onKeyDown={e => focusNextInputOnEnter(e, index)} + autoFocus={inputList.length === 1 && index === 0} + /> + ))} + +
+
+ +
+ ); +}; + +export default SetInitialMemberListModal; diff --git a/client/src/components/Modal/SetInitialMemberListModal/index.ts b/client/src/components/Modal/SetInitialMemberListModal/index.ts new file mode 100644 index 000000000..18098e4f6 --- /dev/null +++ b/client/src/components/Modal/SetInitialMemberListModal/index.ts @@ -0,0 +1 @@ +export {default as SetInitialMemberListModal} from './SetInitialMemberListModal'; diff --git a/client/src/components/Modal/index.ts b/client/src/components/Modal/index.ts new file mode 100644 index 000000000..180063b03 --- /dev/null +++ b/client/src/components/Modal/index.ts @@ -0,0 +1,4 @@ +export {default as SetActionListModal} from './SetActionModal/SetActionListModal'; +export {default as SetInitialMemberListModal} from './SetInitialMemberListModal/SetInitialMemberListModal'; +export {default as SetAllMemberListModal} from './SetAllMemberListModal/SetAllMemberListModal'; +export {default as ModalBasedOnMemberCount} from './ModalBasedOnMemberCount/ModalBasedOnMemberCount'; diff --git a/client/src/components/QueryClientBoundary/QueryClientBoundary.tsx b/client/src/components/QueryClientBoundary/QueryClientBoundary.tsx new file mode 100644 index 000000000..aeec24c3a --- /dev/null +++ b/client/src/components/QueryClientBoundary/QueryClientBoundary.tsx @@ -0,0 +1,24 @@ +import {MutationCache, QueryCache, QueryClient, QueryClientProvider} from '@tanstack/react-query'; + +import {useAppErrorStore} from '@store/appErrorStore'; + +const QueryClientBoundary = ({children}: React.PropsWithChildren) => { + const {updateAppError} = useAppErrorStore(); + + const queryClient = new QueryClient({ + queryCache: new QueryCache({ + onError: (error: Error) => { + updateAppError(error); + }, + }), + mutationCache: new MutationCache({ + onError: (error: Error) => { + updateAppError(error); + }, + }), + }); + + return {children}; +}; + +export default QueryClientBoundary; diff --git a/client/src/components/StepList/BillStepItem.tsx b/client/src/components/StepList/BillStepItem.tsx new file mode 100644 index 000000000..7fed9ef5c --- /dev/null +++ b/client/src/components/StepList/BillStepItem.tsx @@ -0,0 +1,138 @@ +import {DragHandleItem, DragHandleItemContainer, EditableItem, Flex, Text} from 'haengdong-design'; +import {Fragment, useState} from 'react'; +import {useOutletContext} from 'react-router-dom'; + +import {BillStep, MemberReport} from 'types/serviceType'; +import {PutAndDeleteBillActionModal} from '@components/Modal/SetActionModal/PutAndDeleteBillActionModal'; +import {MemberListInBillStep} from '@components/Modal/MemberListInBillStep'; +import {EventPageContextProps} from '@pages/EventPage/EventPageLayout'; +import ExpenseDetailModal from '@components/Modal/ExpenseDetailModal/ExpenseDetailModal'; + +import useSetBillInput from '@hooks/useSetBillInput'; + +interface BillStepItemProps { + step: BillStep; + isOpenBottomSheet: boolean; + setIsOpenBottomSheet: React.Dispatch>; + isAddEditableItem: boolean; + setIsAddEditableItem: React.Dispatch>; + isLastBillItem: boolean; + index: number; +} + +const BillStepItem: React.FC = ({ + step, + isOpenBottomSheet, + setIsOpenBottomSheet, + isAddEditableItem, + setIsAddEditableItem, + isLastBillItem, + index, +}) => { + const {isAdmin} = useOutletContext(); + const {handleBlurBillRequest, handleChangeBillInput, billInput} = useSetBillInput({setIsAddEditableItem}); + + const [clickedIndex, setClickedIndex] = useState(-1); + const [isOpenMemberListInBillStep, setIsOpenMemberListInBillStep] = useState(false); + + const totalPrice = step.actions && step.type === 'BILL' ? step.actions.reduce((acc, cur) => acc + cur.price, 0) : 0; + + const handleDragHandleItemClick = (index: number) => { + setClickedIndex(index); + setIsOpenBottomSheet(true); + }; + + const memberList: MemberReport[] = step.members.map(member => ({ + name: member, + price: totalPrice / step.members.length, + })); + + const handleTopRightTextClick = () => { + setIsOpenMemberListInBillStep(true); + }; + + return ( + <> + + {step.actions && + step.type === 'BILL' && + step.actions.map((action, index) => ( + + handleDragHandleItemClick(index)} + isFixed={action.isFixed} + /> + + {isOpenBottomSheet && clickedIndex === index && isAdmin && ( + + )} + {isOpenBottomSheet && clickedIndex === index && !isAdmin && ( + + )} + + ))} + + {isAddEditableItem && isLastBillItem && ( + { + if (e.key === 'Enter') { + handleBlurBillRequest(); + } + }} + > + handleChangeBillInput('title', e)} + autoFocus + > + + handleChangeBillInput('price', e)} + style={{textAlign: 'right'}} + > + ์› + + + )} + + + + ); +}; + +export default BillStepItem; diff --git a/client/src/components/StepList/MemberStepItem.tsx b/client/src/components/StepList/MemberStepItem.tsx new file mode 100644 index 000000000..ed3f5bfe7 --- /dev/null +++ b/client/src/components/StepList/MemberStepItem.tsx @@ -0,0 +1,38 @@ +import type {MemberStep} from 'types/serviceType'; + +import {DragHandleItem} from 'haengdong-design'; +import {useOutletContext} from 'react-router-dom'; + +import {DeleteMemberActionModal} from '@components/Modal/SetActionModal/DeleteMemberActionModal'; +import {EventPageContextProps} from '@pages/EventPage/EventPageLayout'; + +interface MemberStepItemProps { + step: MemberStep; + isOpenBottomSheet: boolean; + setIsOpenBottomSheet: React.Dispatch>; +} + +const MemberStepItem: React.FC = ({step, isOpenBottomSheet, setIsOpenBottomSheet}) => { + const {isAdmin} = useOutletContext(); + + return ( + <> + name).join(', ')} ${step.type === 'IN' ? '๋“ค์–ด์˜ด' : '๋‚˜๊ฐ'}`} + onClick={() => setIsOpenBottomSheet(prev => !prev)} + /> + {isOpenBottomSheet && isAdmin && ( + + )} + + ); +}; + +export default MemberStepItem; diff --git a/client/src/components/StepList/Step.tsx b/client/src/components/StepList/Step.tsx new file mode 100644 index 000000000..f6c89475b --- /dev/null +++ b/client/src/components/StepList/Step.tsx @@ -0,0 +1,51 @@ +import type {BillStep, MemberStep} from 'types/serviceType'; + +import {useEffect, useState} from 'react'; + +import BillStepItem from './BillStepItem'; +import MemberStepItem from './MemberStepItem'; + +interface StepProps { + step: BillStep | MemberStep; + isAddEditableItem: boolean; + lastBillItemIndex: number; + lastItemIndex: number; + index: number; + setIsAddEditableItem: React.Dispatch>; +} + +const Step = ({step, isAddEditableItem, lastBillItemIndex, lastItemIndex, setIsAddEditableItem, index}: StepProps) => { + const [isOpenBottomSheet, setIsOpenBottomSheet] = useState(false); + const [isLastBillItem, setIsLastBillItem] = useState(false); + + useEffect(() => { + if (index === lastBillItemIndex && lastBillItemIndex === lastItemIndex) { + // index๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋งˆ์ง€๋ง‰ BillStep์ธ์ง€ ํ™•์ธ + setIsLastBillItem(true); + } else { + setIsLastBillItem(false); + } + }, [index, lastBillItemIndex]); + + if (step.actions && step.type === 'BILL') { + return ( + + ); + } else if (step.actions && (step.type === 'IN' || step.type === 'OUT')) { + return ( + + ); + } else { + return <>; + } +}; + +export default Step; diff --git a/client/src/components/StepList/StepList.tsx b/client/src/components/StepList/StepList.tsx new file mode 100644 index 000000000..d6a507247 --- /dev/null +++ b/client/src/components/StepList/StepList.tsx @@ -0,0 +1,76 @@ +import {Flex} from 'haengdong-design'; +import {useEffect, useMemo, useState} from 'react'; + +import {BillStep, MemberStep} from 'types/serviceType'; +import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; + +import Step from './Step'; + +interface StepListProps { + isAddEditableItem?: boolean; + setIsAddEditableItem?: React.Dispatch>; +} + +const StepList = ({isAddEditableItem = false, setIsAddEditableItem = () => {}}: StepListProps) => { + const {data: stepListData} = useRequestGetStepList(); + const [stepList, setStepList] = useState<(MemberStep | BillStep)[]>([]); + const existIndexInStepList = stepList.map((step, index) => ({...step, index})); + const [hasAddedItem, setHasAddedItem] = useState(false); + const nextStepName = stepList.length > 0 ? String(stepList[stepList.length - 1].stepName).match(/.*(?=์ฐจ)/) : ''; + + useEffect(() => { + if (stepListData) { + setStepList(stepListData); + } + }, [stepListData]); + + const lastBillItemIndex = useMemo(() => { + const billSteps = existIndexInStepList.filter(step => step.type === 'BILL'); + + // billSteps ๋ฐฐ์—ด์ด ๋น„์–ด ์žˆ์ง€ ์•Š์œผ๋ฉด ๋งˆ์ง€๋ง‰ ํ•ญ๋ชฉ์˜ index๋ฅผ ๋ฐ˜ํ™˜, ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด -1์„ ๋ฐ˜ํ™˜ + return billSteps.length > 0 ? billSteps.slice(-1)[0].index : -1; + }, [stepList]); + + const lastItemIndex = useMemo(() => { + return existIndexInStepList.length > 0 ? existIndexInStepList.slice(-1)[0].index : -1; + }, [existIndexInStepList]); + + useEffect(() => { + if (hasAddedItem) { + setHasAddedItem(false); + + setStepList(prev => [...prev.filter(({actions}) => actions.length !== 0)]); + } + + if (isAddEditableItem && lastBillItemIndex !== lastItemIndex && !hasAddedItem) { + setStepList(prev => [ + ...prev, + { + type: 'BILL', + stepName: `${Number(nextStepName) + 1}์ฐจ`, + members: [], + actions: [], + }, + ]); + setHasAddedItem(prev => !prev); + } + }, [isAddEditableItem]); + + return ( + + {stepList.map((step, index) => ( + + ))} + + ); +}; + +export default StepList; diff --git a/client/src/components/Toast/Toast.style.ts b/client/src/components/Toast/Toast.style.ts new file mode 100644 index 000000000..a0b5c7cd4 --- /dev/null +++ b/client/src/components/Toast/Toast.style.ts @@ -0,0 +1,65 @@ +import {css, keyframes} from '@emotion/react'; + +import {ToastPosition} from './Toast.type'; + +type ToastMarginStyle = { + position?: ToastPosition; + bottom?: string; + top?: string; +}; + +// ์• ๋‹ˆ๋ฉ”์ด์…˜ ํ‚คํ”„๋ ˆ์ž„ ์ •์˜ +const fadeInWithTransformY = keyframes` + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +`; + +const fadeOutWithTransformY = keyframes` + from { + opacity: 1; + transform: translateY(0); + } + to { + opacity: 0; + transform: translateY(20px); + } +`; + +export const toastMarginStyle = ({position, bottom, top}: ToastMarginStyle) => + css({ + position: 'absolute', + bottom: position === 'bottom' ? `${bottom}` : 'auto', + top: position === 'top' ? `${top}` : 'auto', + left: '50%', + transform: 'translate(-50%)', + + width: '100%', + maxWidth: '48rem', + paddingInline: '1rem', + }); + +export const toastStyle = (isVisible: boolean) => + css({ + width: '100%', + padding: '0.625rem 1rem', + + backgroundColor: 'gray', + boxShadow: '0 0.5rem 0.75rem rgba(0, 0, 0, 0.16);', + + borderRadius: '1.25rem', + + // ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ถ”๊ฐ€ + animation: `${isVisible ? fadeInWithTransformY : fadeOutWithTransformY} 0.5s forwards`, + }); + +export const textStyle = css({ + width: '100%', + color: 'white', + whiteSpace: 'pre-line', +}); diff --git a/client/src/components/Toast/Toast.tsx b/client/src/components/Toast/Toast.tsx new file mode 100644 index 000000000..5bf44d6fb --- /dev/null +++ b/client/src/components/Toast/Toast.tsx @@ -0,0 +1,75 @@ +import {createPortal} from 'react-dom'; +import {useState, useEffect} from 'react'; +import {Button, Flex, Icon, Text} from 'haengdong-design'; + +import {toastStyle, textStyle, toastMarginStyle} from './Toast.style'; +import {ToastProps, ToastType} from './Toast.type'; + +const renderIcon = (type: ToastType) => { + if (type === 'none') return null; + + return ; +}; + +const ANIMATION_TIME = 500; + +const Toast = ({ + type = 'confirm', + top = '0px', + bottom = '0px', + isClickToClose = true, + position = 'bottom', + showingTime = 3000, + message, + onUndo, + onClose, + ...htmlProps +}: ToastProps) => { + const [isVisible, setIsVisible] = useState(true); + const styleProps = {position, top, bottom}; + + useEffect(() => { + const timer = setTimeout(() => { + setIsVisible(false); + setTimeout(() => { + if (onClose) onClose(); + }, ANIMATION_TIME); // fadeOut ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ๊ฐ„๊ณผ ๋™์ผํ•˜๊ฒŒ ์„ค์ • + }, showingTime - ANIMATION_TIME); // ํ† ์ŠคํŠธ๊ฐ€ ๋‚ด๋ ค๊ฐ€๋Š” ์‹œ๊ฐ„ ํ™•๋ณด + + return () => { + clearTimeout(timer); + }; + }, [onClose]); + + const handleClickToClose = () => { + if (!isClickToClose || !onClose) return; + + setIsVisible(false); + setTimeout(() => { + onClose(); + }, ANIMATION_TIME); // fadeOut ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ๊ฐ„๊ณผ ๋™์ผํ•˜๊ฒŒ ์„ค์ • + }; + + return createPortal( +
+
+ + + {renderIcon(type)} + + {message} + + + {onUndo && ( + + )} + +
+
, + document.body, + ); +}; + +export default Toast; diff --git a/client/src/components/Toast/Toast.type.ts b/client/src/components/Toast/Toast.type.ts new file mode 100644 index 000000000..20b92c0db --- /dev/null +++ b/client/src/components/Toast/Toast.type.ts @@ -0,0 +1,22 @@ +export type ToastPosition = 'bottom' | 'top'; +export type ToastType = 'error' | 'confirm' | 'none'; + +export interface ToastStyleProps { + bottom?: string; + top?: string; +} + +export interface ToastOptionProps { + position?: ToastPosition; + type?: ToastType; + onUndo?: () => void; + isClickToClose?: boolean; + onClose?: () => void; + showingTime?: number; +} + +export interface ToastRequiredProps { + message: string; +} + +export type ToastProps = React.ComponentProps<'div'> & ToastStyleProps & ToastOptionProps & ToastRequiredProps; diff --git a/client/src/constants/errorMessage.ts b/client/src/constants/errorMessage.ts new file mode 100644 index 000000000..42703bdf0 --- /dev/null +++ b/client/src/constants/errorMessage.ts @@ -0,0 +1,49 @@ +type ErrorMessage = Record; + +export const SERVER_ERROR_MESSAGES: ErrorMessage = { + EVENT_NOT_FOUND: '์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค.', + EVENT_NAME_LENGTH_INVALID: 'ํ–‰์‚ฌ ์ด๋ฆ„์€ 2์ž ์ด์ƒ 30์ž ์ดํ•˜๋งŒ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.', + EVENT_NAME_CONSECUTIVE_SPACES: 'ํ–‰์‚ฌ ์ด๋ฆ„์—๋Š” ๊ณต๋ฐฑ ๋ฌธ์ž๊ฐ€ ์—ฐ์†๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.', + EVENT_PASSWORD_FORMAT_INVALID: '๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” 4์ž๋ฆฌ ์ˆซ์ž๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.', + + ACTION_NOT_FOUND: '์กด์žฌํ•˜์ง€ ์•Š๋Š” ์•ก์…˜์ž…๋‹ˆ๋‹ค.', + + MEMBER_NAME_LENGTH_INVALID: '๋ฉค๋ฒ„ ์ด๋ฆ„์€ 1์ž ์ด์ƒ 4์ž ์ดํ•˜๋งŒ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.', + MEMBER_NAME_DUPLICATE: '์ค‘๋ณต๋œ ํ–‰์‚ฌ ์ฐธ์—ฌ ์ธ์› ์ด๋ฆ„์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.', + MEMBER_NOT_EXIST: 'ํ˜„์žฌ ์ฐธ์—ฌํ•˜๊ณ  ์žˆ์ง€ ์•Š์€ ์ธ์›์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.', + MEMBER_ALREADY_EXIST: 'ํ˜„์žฌ ์ฐธ์—ฌํ•˜๊ณ  ์žˆ๋Š” ์ธ์›์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.', + + MEMBER_ACTION_NOT_FOUND: '์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ฉค๋ฒ„ ์•ก์…˜์ž…๋‹ˆ๋‹ค.', + MEMBER_ACTION_STATUS_INVALID: '์œ ํšจํ•˜์ง€ ์•Š์€ ๋ฉค๋ฒ„ ์•ก์…˜ ์ƒํƒœ์ž…๋‹ˆ๋‹ค.', + + BILL_ACTION_NOT_FOUND: '์กด์žฌํ•˜์ง€ ์•Š๋Š” ์ง€์ถœ ์•ก์…˜์ž…๋‹ˆ๋‹ค.', + BILL_ACTION_TITLE_INVALID: '์•ž๋’ค ๊ณต๋ฐฑ์„ ์ œ๊ฑฐํ•œ ์ง€์ถœ ๋‚ด์—ญ ์ œ๋ชฉ์€ %d์ž ~ %d์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.', + BILL_ACTION_PRICE_INVALID: '์ง€์ถœ ๊ธˆ์•ก์€ 10,000,000 ์ดํ•˜์˜ ์ž์—ฐ์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.', + + REQUEST_EMPTY: '์ž…๋ ฅ ๊ฐ’์€ ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.', + MESSAGE_NOT_READABLE: '์ฝ์„ ์ˆ˜ ์—†๋Š” ์š”์ฒญ์ž…๋‹ˆ๋‹ค.', + NO_RESOURCE_REQUEST: '์กด์žฌํ•˜์ง€ ์•Š๋Š” ์ž์›์ž…๋‹ˆ๋‹ค.', + REQUEST_METHOD_NOT_SUPPORTED: '์ง€์›ํ•˜์ง€ ์•Š๋Š” ์š”์ฒญ ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค.', + + INTERNAL_SERVER_ERROR: '์„œ๋ฒ„ ๋‚ด๋ถ€์— ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.', + + PASSWORD_INVALID: '๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.', + TOKEN_NOT_FOUND: 'ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.', + TOKEN_EXPIRED: '๋งŒ๋ฃŒ๋œ ํ† ํฐ์ž…๋‹ˆ๋‹ค.', + TOKEN_INVALID: '์œ ํšจํ•˜์ง€ ์•Š์€ ํ† ํฐ์ž…๋‹ˆ๋‹ค.', + FORBIDDEN: '์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค.', + + UNHANDLED: '์•Œ ์ˆ˜ ์—†๋Š” ์—๋Ÿฌ์ž…๋‹ˆ๋‹ค.', +}; + +export const ERROR_MESSAGE = { + eventName: 'ํ–‰์‚ฌ ์ด๋ฆ„์€ 30์ž ์ดํ•˜๋งŒ ๊ฐ€๋Šฅํ•ด์š”', + eventPasswordType: '๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ์ˆซ์ž๋งŒ ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•ด์š”', + memberName: '์ฐธ์—ฌ์ž ์ด๋ฆ„์€ 4์ž ์ดํ•˜์˜ ํ•œ๊ธ€, ์˜์–ด๋งŒ ๊ฐ€๋Šฅํ•ด์š”', + purchasePrice: '10,000,000์› ์ดํ•˜์˜ ์ˆซ์ž๋งŒ ์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•ด์š”', + purchaseTitle: '์ง€์ถœ ์ด๋ฆ„์€ 30์ž ์ดํ•˜์˜ ํ•œ๊ธ€, ์˜์–ด, ์ˆซ์ž๋งŒ ๊ฐ€๋Šฅํ•ด์š”', + preventEmpty: '๊ฐ’์€ ๋น„์–ด์žˆ์„ ์ˆ˜ ์—†์–ด์š”', + invalidInput: '์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์€ ์ž…๋ ฅ์ด์—์š”.', +}; + +export const UNKNOWN_ERROR = 'UNKNOWN_ERROR'; diff --git a/client/src/constants/password.ts b/client/src/constants/password.ts new file mode 100644 index 000000000..cfb26b39c --- /dev/null +++ b/client/src/constants/password.ts @@ -0,0 +1 @@ +export const PASSWORD_LENGTH = 4; diff --git a/client/src/constants/queryKeys.ts b/client/src/constants/queryKeys.ts new file mode 100644 index 000000000..17f3f4586 --- /dev/null +++ b/client/src/constants/queryKeys.ts @@ -0,0 +1,10 @@ +const QUERY_KEYS = { + stepList: 'stepList', + eventName: 'eventName', + allMemberList: 'allMemberList', + currentInMember: 'currentInMember', + memberReport: 'memberReport', + memberReportInAction: 'memberReportInAction', +}; + +export default QUERY_KEYS; diff --git a/client/src/constants/regExp.ts b/client/src/constants/regExp.ts new file mode 100644 index 000000000..4d910ac99 --- /dev/null +++ b/client/src/constants/regExp.ts @@ -0,0 +1,8 @@ +const REGEXP = { + eventPassword: /^[0-9]*$/, + memberName: /^[ใ„ฑ-ใ…Žใ…-ใ…ฃ๊ฐ€-ํžฃa-zA-Z\s]*$/, + purchaseTitle: /^[ใ„ฑ-ใ…Žใ…-ใ…ฃ๊ฐ€-ํžฃa-zA-Z0-9\s]*$/, + eventUrl: /\/event\/([a-zA-Z0-9-]+)\//, +}; + +export default REGEXP; diff --git a/client/src/constants/routerUrls.ts b/client/src/constants/routerUrls.ts new file mode 100644 index 000000000..6a3634c3b --- /dev/null +++ b/client/src/constants/routerUrls.ts @@ -0,0 +1,10 @@ +export const ROUTER_URLS = { + main: '/', + eventCreateName: '/event/create/name', + eventCreatePassword: '/event/create/password', + eventCreateComplete: '/event/create/complete', + event: '/event', // TODO: (@weadie) baseurl์„ ์–ด๋–ป๊ฒŒ ๊ด€๋ฆฌํ•  ๊ฒƒ์ธ๊ฐ€? + eventLogin: '/event/:eventId/login', + eventManage: '/event/:eventId/admin', + home: '/event/:eventId/home', +}; diff --git a/client/src/constants/rule.ts b/client/src/constants/rule.ts new file mode 100644 index 000000000..4b78031b9 --- /dev/null +++ b/client/src/constants/rule.ts @@ -0,0 +1,8 @@ +const RULE = { + maxEventNameLength: 30, + maxEventPasswordLength: 4, + maxMemberNameLength: 4, + maxPrice: 10000000, +}; + +export default RULE; diff --git a/client/src/errors/FetchError.ts b/client/src/errors/FetchError.ts new file mode 100644 index 000000000..9123a80b5 --- /dev/null +++ b/client/src/errors/FetchError.ts @@ -0,0 +1,23 @@ +import {FetchErrorType} from '../types/fetchErrorType'; + +class FetchError extends Error { + requestBody; + status; + endpoint; + errorInfo; + method; + + constructor({requestBody, status, endpoint, errorInfo, method, name, message}: FetchErrorType) { + super(errorInfo.errorCode); + + this.requestBody = requestBody; + this.status = status; + this.endpoint = endpoint; + this.errorInfo = errorInfo; + this.method = method; + this.name = name; + this.message = message; + } +} + +export default FetchError; diff --git a/client/src/global.d.ts b/client/src/global.d.ts new file mode 100644 index 000000000..dbf6320af --- /dev/null +++ b/client/src/global.d.ts @@ -0,0 +1,11 @@ +declare module '*.svg'; + +declare namespace NodeJS { + interface ProcessEnv { + readonly NODE_ENV: 'development' | 'production' | 'test'; + + // env keys + readonly API_BASE_URL: string; + readonly AMPLITUDE_KEY: string; + } +} diff --git a/client/src/hooks/queries/useRequestDeleteAllMemberList.ts b/client/src/hooks/queries/useRequestDeleteAllMemberList.ts new file mode 100644 index 000000000..da6fc4223 --- /dev/null +++ b/client/src/hooks/queries/useRequestDeleteAllMemberList.ts @@ -0,0 +1,28 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {requestDeleteAllMemberList} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +interface DeleteAllMemberListMutationProps { + memberName: string; +} + +const useRequestDeleteAllMemberList = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({memberName}: DeleteAllMemberListMutationProps) => requestDeleteAllMemberList({eventId, memberName}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); + queryClient.removeQueries({queryKey: [QUERY_KEYS.memberReportInAction]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + }, + }); +}; + +export default useRequestDeleteAllMemberList; diff --git a/client/src/hooks/queries/useRequestDeleteBillAction.ts b/client/src/hooks/queries/useRequestDeleteBillAction.ts new file mode 100644 index 000000000..28be9dfd1 --- /dev/null +++ b/client/src/hooks/queries/useRequestDeleteBillAction.ts @@ -0,0 +1,26 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {requestDeleteBillAction} from '@apis/request/bill'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +interface DeleteBillActionMutationProps { + actionId: number; +} + +const useRequestDeleteBillAction = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({actionId}: DeleteBillActionMutationProps) => requestDeleteBillAction({eventId, actionId}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + }, + }); +}; + +export default useRequestDeleteBillAction; diff --git a/client/src/hooks/queries/useRequestDeleteMemberAction.ts b/client/src/hooks/queries/useRequestDeleteMemberAction.ts new file mode 100644 index 000000000..08e69ac1f --- /dev/null +++ b/client/src/hooks/queries/useRequestDeleteMemberAction.ts @@ -0,0 +1,28 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {requestDeleteMemberAction} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +interface DeleteMemberActionMutationProps { + actionId: number; +} + +const useRequestDeleteMemberAction = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({actionId}: DeleteMemberActionMutationProps) => requestDeleteMemberAction({eventId, actionId}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReportInAction]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); + }, + }); +}; + +export default useRequestDeleteMemberAction; diff --git a/client/src/hooks/queries/useRequestGetAllMemberList.ts b/client/src/hooks/queries/useRequestGetAllMemberList.ts new file mode 100644 index 000000000..531285fd6 --- /dev/null +++ b/client/src/hooks/queries/useRequestGetAllMemberList.ts @@ -0,0 +1,18 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetAllMemberList} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetAllMemberList = () => { + const eventId = getEventIdByUrl(); + + return useQuery({ + queryKey: [QUERY_KEYS.allMemberList], + queryFn: () => requestGetAllMemberList({eventId}), + }); +}; + +export default useRequestGetAllMemberList; diff --git a/client/src/hooks/queries/useRequestGetCurrentInMemberList.ts b/client/src/hooks/queries/useRequestGetCurrentInMemberList.ts new file mode 100644 index 000000000..31dc058c2 --- /dev/null +++ b/client/src/hooks/queries/useRequestGetCurrentInMemberList.ts @@ -0,0 +1,18 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetCurrentInMemberList} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetCurrentInMemberList = () => { + const eventId = getEventIdByUrl(); + + return useQuery({ + queryKey: [QUERY_KEYS.currentInMember], + queryFn: () => requestGetCurrentInMemberList({eventId}), + }); +}; + +export default useRequestGetCurrentInMemberList; diff --git a/client/src/hooks/queries/useRequestGetEventName.ts b/client/src/hooks/queries/useRequestGetEventName.ts new file mode 100644 index 000000000..6ddb21858 --- /dev/null +++ b/client/src/hooks/queries/useRequestGetEventName.ts @@ -0,0 +1,18 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetEventName} from '@apis/request/event'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetEventName = () => { + const eventId = getEventIdByUrl(); + + return useQuery({ + queryKey: [QUERY_KEYS.eventName], + queryFn: () => requestGetEventName({eventId}), + }); +}; + +export default useRequestGetEventName; diff --git a/client/src/hooks/queries/useRequestGetMemberReportList.ts b/client/src/hooks/queries/useRequestGetMemberReportList.ts new file mode 100644 index 000000000..fe3372d35 --- /dev/null +++ b/client/src/hooks/queries/useRequestGetMemberReportList.ts @@ -0,0 +1,17 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetMemberReportList} from '@apis/request/report'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetMemberReportList = () => { + const eventId = getEventIdByUrl(); + + return useQuery({ + queryKey: [QUERY_KEYS.memberReport], + queryFn: () => requestGetMemberReportList({eventId}), + }); +}; +export default useRequestGetMemberReportList; diff --git a/client/src/hooks/queries/useRequestGetMemberReportListInAction.ts b/client/src/hooks/queries/useRequestGetMemberReportListInAction.ts new file mode 100644 index 000000000..85b458228 --- /dev/null +++ b/client/src/hooks/queries/useRequestGetMemberReportListInAction.ts @@ -0,0 +1,24 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetMemberReportListInAction} from '@apis/request/bill'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetMemberReportListInAction = (actionId: number) => { + const eventId = getEventIdByUrl(); + + const {data, ...queryResult} = useQuery({ + queryKey: [QUERY_KEYS.memberReportInAction, actionId], + queryFn: () => requestGetMemberReportListInAction({eventId, actionId}), + select: data => data.members, + }); + + return { + memberReportListInActionFromServer: data ?? [], + queryResult, + }; +}; + +export default useRequestGetMemberReportListInAction; diff --git a/client/src/hooks/queries/useRequestGetStepList.ts b/client/src/hooks/queries/useRequestGetStepList.ts new file mode 100644 index 000000000..7dfc1799c --- /dev/null +++ b/client/src/hooks/queries/useRequestGetStepList.ts @@ -0,0 +1,30 @@ +import {useQuery} from '@tanstack/react-query'; +import {useEffect} from 'react'; + +import {requestGetStepList} from '@apis/request/stepList'; + +import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetStepList = () => { + const eventId = getEventIdByUrl(); + const {updateTotalExpenseAmount} = useTotalExpenseAmountStore(); + + const queryResult = useQuery({ + queryKey: [QUERY_KEYS.stepList], + queryFn: () => requestGetStepList({eventId}), + }); + + useEffect(() => { + if (queryResult.isSuccess && queryResult.data) { + updateTotalExpenseAmount(queryResult.data); + } + }, [queryResult.data, queryResult.isSuccess, updateTotalExpenseAmount]); + + return queryResult; +}; + +export default useRequestGetStepList; diff --git a/client/src/hooks/queries/useRequestPostAuthentication.ts b/client/src/hooks/queries/useRequestPostAuthentication.ts new file mode 100644 index 000000000..e533a501b --- /dev/null +++ b/client/src/hooks/queries/useRequestPostAuthentication.ts @@ -0,0 +1,23 @@ +import {useMutation} from '@tanstack/react-query'; +import {useNavigate} from 'react-router-dom'; + +import {requestPostAuthentication} from '@apis/request/auth'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +const useRequestPostAuthenticate = () => { + const eventId = getEventIdByUrl(); + const navigate = useNavigate(); + + return useMutation({ + mutationFn: () => requestPostAuthentication({eventId}), + onError: () => { + // ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ + navigate(`${ROUTER_URLS.event}/${eventId}/login`); + }, + }); +}; + +export default useRequestPostAuthenticate; diff --git a/client/src/hooks/queries/useRequestPostBillList.ts b/client/src/hooks/queries/useRequestPostBillList.ts new file mode 100644 index 000000000..676da9d85 --- /dev/null +++ b/client/src/hooks/queries/useRequestPostBillList.ts @@ -0,0 +1,27 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {requestPostBillList} from '@apis/request/bill'; +import {Bill} from 'types/serviceType'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +interface PostBillActionMutationProps { + billList: Bill[]; +} + +const useRequestPostBillList = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({billList}: PostBillActionMutationProps) => requestPostBillList({eventId, billList}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + }, + }); +}; + +export default useRequestPostBillList; diff --git a/client/src/hooks/queries/useRequestPostEvent.ts b/client/src/hooks/queries/useRequestPostEvent.ts new file mode 100644 index 000000000..5327710fc --- /dev/null +++ b/client/src/hooks/queries/useRequestPostEvent.ts @@ -0,0 +1,16 @@ +import {useMutation} from '@tanstack/react-query'; + +import {requestPostNewEvent} from '@apis/request/event'; + +interface PostEventMutationProps { + eventName: string; + password: number; +} + +const usePostEvent = () => { + return useMutation({ + mutationFn: ({eventName, password}: PostEventMutationProps) => requestPostNewEvent({eventName, password}), + }); +}; + +export default usePostEvent; diff --git a/client/src/hooks/queries/useRequestPostLogin.ts b/client/src/hooks/queries/useRequestPostLogin.ts new file mode 100644 index 000000000..21dce1791 --- /dev/null +++ b/client/src/hooks/queries/useRequestPostLogin.ts @@ -0,0 +1,26 @@ +import {useMutation} from '@tanstack/react-query'; +import {useNavigate} from 'react-router-dom'; + +import {requestPostToken} from '@apis/request/auth'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +interface PostLoginMutationProps { + password: string; +} + +const useRequestPostLogin = () => { + const eventId = getEventIdByUrl(); + const navigate = useNavigate(); + + return useMutation({ + mutationFn: ({password}: PostLoginMutationProps) => requestPostToken({eventId, password}), + onSuccess: () => { + navigate(`${ROUTER_URLS.event}/${eventId}/admin`); + }, + }); +}; + +export default useRequestPostLogin; diff --git a/client/src/hooks/queries/useRequestPostMemberList.ts b/client/src/hooks/queries/useRequestPostMemberList.ts new file mode 100644 index 000000000..8ed69db08 --- /dev/null +++ b/client/src/hooks/queries/useRequestPostMemberList.ts @@ -0,0 +1,37 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {MemberType} from 'types/serviceType'; +import {requestPostMemberList} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +interface PostMemberListMutationProps { + type: MemberType; + memberNameList: string[]; +} + +const useRequestPostMemberList = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({type, memberNameList}: PostMemberListMutationProps) => + requestPostMemberList({eventId, type, memberNameList}), + // TODO: (@todari) : ๋‚™๊ด€์  ์—…๋ฐ์ดํŠธ ์ ๊ณ  ์žˆ์—ˆ์–ด์šฉ + // onMutate: async ({type, memberNameList}) => { + // await queryClient.cancelQueries({queryKey: [QUERY_KEYS.stepList]}); + // const previousStepList = queryClient.getQueryData([QUERY_KEYS.stepList]); + // queryClient.setQueryData([QUERY_KEYS.stepList], (prev: (MemberStep | BillStep)[]) => prev && { + // }); + // }, + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + }, + }); +}; + +export default useRequestPostMemberList; diff --git a/client/src/hooks/queries/useRequestPutAllMemberList.ts b/client/src/hooks/queries/useRequestPutAllMemberList.ts new file mode 100644 index 000000000..4bd746d0c --- /dev/null +++ b/client/src/hooks/queries/useRequestPutAllMemberList.ts @@ -0,0 +1,28 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {MemberChange, requestPutAllMemberList} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +interface PutAllMemberListMutationProps { + members: MemberChange[]; +} + +const useRequestPutAllMemberList = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({members}: PutAllMemberListMutationProps) => requestPutAllMemberList({eventId, members}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); + queryClient.removeQueries({queryKey: [QUERY_KEYS.memberReportInAction]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + }, + }); +}; + +export default useRequestPutAllMemberList; diff --git a/client/src/hooks/queries/useRequestPutBillAction.ts b/client/src/hooks/queries/useRequestPutBillAction.ts new file mode 100644 index 000000000..a58da8ea4 --- /dev/null +++ b/client/src/hooks/queries/useRequestPutBillAction.ts @@ -0,0 +1,29 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {requestPutBillAction} from '@apis/request/bill'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +interface PutBillActionMutationProps { + actionId: number; + title: string; + price: number; +} + +const useRequestPutBillAction = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({actionId, title, price}: PutBillActionMutationProps) => + requestPutBillAction({eventId, actionId, title, price}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + }, + }); +}; + +export default useRequestPutBillAction; diff --git a/client/src/hooks/queries/useRequestPutMemberReportListInAction.ts b/client/src/hooks/queries/useRequestPutMemberReportListInAction.ts new file mode 100644 index 000000000..a87fa44f1 --- /dev/null +++ b/client/src/hooks/queries/useRequestPutMemberReportListInAction.ts @@ -0,0 +1,49 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {MemberReportList, requestPutMemberReportListInAction} from '@apis/request/bill'; +import {MemberReportInAction} from 'types/serviceType'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestPutMemberReportListInAction = (actionId: number) => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + const {mutate, ...mutationProps} = useMutation({ + mutationFn: (members: MemberReportInAction[]) => requestPutMemberReportListInAction({eventId, actionId, members}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + queryClient.removeQueries({queryKey: [QUERY_KEYS.memberReportInAction, actionId]}); + }, + onMutate: async (newMembers: MemberReportInAction[]) => { + await queryClient.cancelQueries({queryKey: [QUERY_KEYS.memberReportInAction, actionId]}); + + const previousMembers = queryClient.getQueryData([QUERY_KEYS.memberReportInAction, actionId]); + + queryClient.setQueryData([QUERY_KEYS.memberReportInAction, actionId], (oldData: MemberReportList) => ({ + ...oldData, + members: oldData.members.map((member: MemberReportInAction) => { + const updatedMember = newMembers.find(m => m.name === member.name); + return updatedMember ? {...member, ...updatedMember} : member; + }), + })); + + return {previousMembers}; + }, + onError: (err, newMembers, context) => { + if (context?.previousMembers) { + queryClient.setQueryData([QUERY_KEYS.memberReportInAction, actionId], context.previousMembers); + } + }, + }); + + return { + putMemberReportListInAction: mutate, + mutationProps, + }; +}; + +export default useRequestPutMemberReportListInAction; diff --git a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx new file mode 100644 index 000000000..38836f677 --- /dev/null +++ b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx @@ -0,0 +1,139 @@ +import {renderHook, waitFor} from '@testing-library/react'; +import {MemoryRouter} from 'react-router-dom'; +import {act} from 'react'; +import {HDesignProvider} from 'haengdong-design'; + +import {BillStep, MemberAction, MemberStep} from 'types/serviceType'; +import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; +import AppErrorBoundary from '@components/AppErrorBoundary/ErrorCatcher'; +import QueryClientBoundary from '@components/QueryClientBoundary/QueryClientBoundary'; +import {ToastProvider} from '@hooks/useToast/ToastProvider'; + +import stepListJson from '@mocks/stepList.json'; +import invalidMemberStepListJson from '@mocks/invalidMemberStepList.json'; + +import useDeleteMemberAction from './useDeleteMemberAction'; + +const stepListMockData = stepListJson as (BillStep | MemberStep)[]; +let memberActionList: MemberAction[] = []; + +// filter๋กœ๋Š” type narrowing์ด ์•ˆ๋˜์–ด ๋ถ€๋“์ดํ•˜๊ฒŒ for ๋ฌธ์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. +for (let i = 0; i < stepListMockData.length; i++) { + const curAction = stepListMockData[i]; + if (curAction.type !== 'BILL') curAction.actions.forEach(action => memberActionList.push(action)); +} + +describe('useDeleteMemberAction', () => { + const initializeProvider = (list: MemberAction[] = memberActionList) => + renderHook( + () => { + return { + stepListResult: useRequestGetStepList(), + deleteMemberActionList: useDeleteMemberAction({ + memberActionList: list, + setIsBottomSheetOpened: () => {}, + showToastAlreadyExistMemberAction: () => {}, + showToastExistSameMemberFromAfterStep: () => {}, + }), + }; + }, + { + wrapper: ({children}) => ( + + + + + {children} + + + + + ), + }, + ); + + it('๋ฉค๋ฒ„๋ฅผ ์‚ญ์ œํ•  ๋ฉค๋ฒ„ ๋ชฉ๋ก์— ์ถ”๊ฐ€ํ•œ๋‹ค.', async () => { + const {result} = initializeProvider(); + + // stepList ๊ฐ’์ด ์ฑ„์›Œ์ง€๊ธธ ๋Œ€๊ธฐํ•ฉ๋‹ˆ๋‹ค. + await waitFor(() => { + expect(result.current.stepListResult.data).not.toStrictEqual([]); + }); + + act(() => { + const memberAction = { + actionId: 1, + name: '๋ง์ตธ', + price: null, + sequence: 1, + isFixed: false, + }; + + result.current.deleteMemberActionList.addDeleteMemberAction(memberAction); + }); + + expect(result.current.deleteMemberActionList.aliveActionList).not.toContainEqual({ + actionId: 1, + name: '๋ง์ตธ', + price: null, + sequence: 1, + }); + }); + + it('์‚ญ์ œํ•  ๋ฉค๋ฒ„ ๋ชฉ๋ก์— ์žˆ๋Š” ๋ฉค๋ฒ„๋“ค์„ ๋ชจ๋‘ ์‚ญ์ œํ•ด ์‚ญ์ œํ•  ๋ฉค๋ฒ„ ๋ชฉ๋ก์„ ๋น„์šด๋‹ค.', async () => { + const {result} = initializeProvider(); + + // stepList ๊ฐ’์ด ์ฑ„์›Œ์ง€๊ธธ ๋Œ€๊ธฐํ•ฉ๋‹ˆ๋‹ค. + await waitFor(() => { + expect(result.current.stepListResult.data).not.toStrictEqual([]); + }); + + await act(async () => { + memberActionList.forEach(memberAction => { + result.current.deleteMemberActionList.addDeleteMemberAction(memberAction); + }); + }); + + await act(async () => result.current.deleteMemberActionList.deleteMemberActionList()); + + await waitFor(() => { + expect(result.current.deleteMemberActionList.aliveActionList).toHaveLength(0); + }); + }); + + it('์‚ญ์ œ ์š”์ฒญ์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๊ฒฝ์šฐ ์‚ญ์ œํ•  ๋ฉค๋ฒ„ ๋ชฉ๋ก์„ ์ฒ˜์Œ์˜ ์ƒํƒœ๋กœ ๋Œ๋ ค๋†“๋Š”๋‹ค.', async () => { + /** + * ์ด ํ…Œ์ŠคํŠธ๋Š” deleteMemberAction์„ ์‹คํ–‰ํ–ˆ์„ ๋•Œ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜๋Š” ๊ฒฝ์šฐ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•ด ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. + * ์—ฌ๊ธฐ์„œ ์‚ฌ์šฉํ•˜๋Š” stepList ๋ชฉ๋ฐ์ดํ„ฐ๋Š” 999 actionId๋ฅผ ๊ฐ€์ง„ MemberAction์ด ์žˆ๋Š” ๋ฐ์ดํ„ฐ์ž…๋‹ˆ๋‹ค. + * 999 actionId๋Š” ํ˜„์žฌ ๋ชจํ‚น๋˜์–ด์žˆ๋Š” msw์—์„œ ์˜ค๋ฅ˜๋ฅผ ๋ฑ‰๋„๋ก ํ•˜๋Š” id์ž…๋‹ˆ๋‹ค. ์ด๋Š” ์˜ค๋ฅ˜ ์ƒํ™ฉ์„ ์‹œ์—ฐํ•˜๊ธฐ ์œ„ํ•œ ์ž„์˜ ๋ชจํ‚น์ž…๋‹ˆ๋‹ค. + * (999๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ๋Š” ๋ชจ๋‘ ์ •์ƒ ์‘๋‹ต ๋ฐ˜ํ™˜) + */ + + // 999 actionId๋ฅผ ๊ฐ€์ง„ MemberAction์ด ์žˆ๋Š” stepListJson ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด MemberActions []์œผ๋กœ ์ •์ œํ•ฉ๋‹ˆ๋‹ค. + const invalidMemberStepListMockData = invalidMemberStepListJson as (BillStep | MemberStep)[]; + let memberActionList: MemberAction[] = []; + + for (let i = 0; i < invalidMemberStepListMockData.length; i++) { + const curAction = invalidMemberStepListMockData[i]; + if (curAction.type !== 'BILL') curAction.actions.forEach(action => memberActionList.push(action)); + } + + // ์˜ค๋ฅ˜ ๋ฉค๋ฒ„๊ฐ€ ํฌํ•จ๋œ memberAction[]์„ useDeleteMemberAction์˜ ์ดˆ๊ธฐ๊ฐ’์œผ๋กœ ์ฃผ์ž…ํ•ฉ๋‹ˆ๋‹ค. + const {result} = initializeProvider(memberActionList); + + // stepList ๊ฐ’์ด ์ฑ„์›Œ์ง€๊ธธ ๋Œ€๊ธฐํ•ฉ๋‹ˆ๋‹ค. + await waitFor(() => { + expect(result.current.stepListResult.data).not.toStrictEqual([]); + }); + + await act(async () => { + const memberAction = memberActionList[0]; // ํ˜„์žฌ 0๋ฒˆ ์ฐธ์—ฌ์ž๋Š” actionId๊ฐ€ 999 ์ด๊ณ , 999 actionId๋Š” ์„œ๋ฒ„์—์„œ ์—๋Ÿฌ๋ฅผ ๋ฑ‰๋„๋ก ์กฐ์ž‘๋œ ์ƒํ™ฉ์ž…๋‹ˆ๋‹ค. + result.current.deleteMemberActionList.addDeleteMemberAction(memberAction); + }); + + await act(async () => result.current.deleteMemberActionList.deleteMemberActionList()); + + // ์‚ญ์ œ ์š”์ฒญ์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— aliveActionList๋ฅผ ์ดˆ๊ธฐ์— ์ฃผ์ž…ํ–ˆ๋˜ ๊ฐ’์œผ๋กœ ๋‹ค์‹œ ๋Œ๋ ค๋†“๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. + expect(result.current.deleteMemberActionList.aliveActionList).toStrictEqual(memberActionList); + }); +}); diff --git a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx new file mode 100644 index 000000000..913087a59 --- /dev/null +++ b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx @@ -0,0 +1,86 @@ +import type {MemberAction} from 'types/serviceType'; + +import {useState} from 'react'; + +import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; +import useRequestDeleteMemberAction from '@hooks/queries/useRequestDeleteMemberAction'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +type UseDeleteMemberActionProps = { + memberActionList: MemberAction[]; + setIsBottomSheetOpened: React.Dispatch>; + showToastAlreadyExistMemberAction: () => void; + showToastExistSameMemberFromAfterStep: (name: string) => void; +}; + +const useDeleteMemberAction = ({ + memberActionList, + setIsBottomSheetOpened, + showToastAlreadyExistMemberAction, + showToastExistSameMemberFromAfterStep, +}: UseDeleteMemberActionProps) => { + const {data: stepListData} = useRequestGetStepList(); + const stepList = stepListData ?? []; + const {mutate: deleteMemberActionMutate} = useRequestDeleteMemberAction(); + + const [deleteActionList, setDeleteActionList] = useState([]); + + const eventId = getEventIdByUrl(); + + const deleteMemberAction = async (actionId: number) => { + deleteMemberActionMutate( + {actionId}, + { + onError: () => { + setDeleteActionList([]); + }, + }, + ); + setIsBottomSheetOpened(false); + }; + + // TODO: (@cookie: ์ถ”ํ›„์— ๋ฐ˜๋ณต๋ฌธ์œผ๋กœ deleteํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ํ•œ ๋ฒˆ์— ๋ชจ์•„์„œ delete ์ฒ˜๋ฆฌํ•˜๊ธฐ (backend์— ๋ฌธ์˜)) + const deleteMemberActionList = async () => { + for (const {actionId} of deleteActionList) { + await deleteMemberAction(actionId); + } + }; + + const checkAlreadyExistMemberAction = (memberAction: MemberAction, showToast: () => void) => { + if (!memberActionList.includes(memberAction)) { + showToast(); + } + }; + + const checkExistSameMemberFromAfterStep = (memberAction: MemberAction, showToast: () => void) => { + if (isExistSameMemberFromAfterStep(memberAction)) { + showToast(); + } + }; + + const addDeleteMemberAction = (memberAction: MemberAction) => { + checkAlreadyExistMemberAction(memberAction, showToastAlreadyExistMemberAction); + checkExistSameMemberFromAfterStep(memberAction, () => showToastExistSameMemberFromAfterStep(memberAction.name)); + setDeleteActionList(prev => [...prev, memberAction]); + }; + + const isExistSameMemberFromAfterStep = (memberAction: MemberAction) => { + const memberActionList = stepList + .filter(step => step.type !== 'BILL') + .map(({actions}) => actions) + .flat(); + const currentActionIndex = memberActionList.findIndex(action => action.actionId === memberAction.actionId); + const memberActionListAfterCurrentAction = memberActionList.slice(Math.max(currentActionIndex - 1, 0)); + const memberNameList = memberActionListAfterCurrentAction.map(({name}) => name); + + return memberNameList.filter(member => member === memberAction.name).length >= 2; + }; + + const aliveActionList = memberActionList.filter( + memberAction => !deleteActionList.some(deleteAction => deleteAction.actionId === memberAction.actionId), + ); + return {aliveActionList, deleteMemberActionList, addDeleteMemberAction}; +}; + +export default useDeleteMemberAction; diff --git a/client/src/hooks/useDynamicInput.tsx b/client/src/hooks/useDynamicInput.tsx new file mode 100644 index 000000000..452add193 --- /dev/null +++ b/client/src/hooks/useDynamicInput.tsx @@ -0,0 +1,142 @@ +import {useEffect, useRef} from 'react'; + +import {ValidateResult} from '@utils/validate/type'; + +import useInput from './useInput'; + +type InputValue = { + value: string; + index: number; +}; + +export type ReturnUseDynamicInput = { + inputList: InputValue[]; + inputRefList: React.MutableRefObject<(HTMLInputElement | null)[]>; + errorMessage: string | null; + canSubmit: boolean; + errorIndexList: number[]; + handleChange: (index: number, value: string) => void; + handleInputChange: (index: number, event: React.ChangeEvent) => void; + deleteEmptyInputElementOnBlur: () => void; + getFilledInputList: (list?: InputValue[]) => InputValue[]; + focusNextInputOnEnter: (e: React.KeyboardEvent, index: number) => void; + setInputValueTargetIndex: (index: number, value: string) => void; + resetInputValue: () => void; +}; + +const useDynamicInput = (validateFunc: (name: string) => ValidateResult): ReturnUseDynamicInput => { + const initialInputList = [{index: 0, value: ''}]; + const inputRefList = useRef<(HTMLInputElement | null)[]>([]); + + const {inputList, errorMessage, errorIndexList, canSubmit, handleChange, setInputList} = useInput({ + validateFunc, + initialInputList, + }); + + useEffect(() => { + if (inputRefList.current.length <= 0) return; + + const lastInput = inputRefList.current[inputRefList.current.length - 1]; + + if (lastInput) { + lastInput.scrollIntoView({behavior: 'smooth', block: 'center'}); + } + }, [inputList]); + + const handleInputChange = (index: number, event: React.ChangeEvent) => { + const {value} = event.target; + + makeNewInputWhenFirstCharacterInput(index, value); + handleChange(index, value); + }; + + const makeNewInputWhenFirstCharacterInput = (index: number, value: string) => { + if (isLastInputFilled(index, value) && value.trim().length !== 0) { + // ๋งˆ์ง€๋ง‰ ์ธํ’‹์ด ํ•œ ์ž๋ผ๋„ ์ฑ„์›Œ์ง„๋‹ค๋ฉด ์ƒˆ๋กœ์šด ์ธํ’‹์„ ์ƒ์„ฑํ•ด ๊ฐ„ํŽธํ•œ ๋‹ค์Œ ์ž…๋ ฅ์„ ์œ ๋„ํ•ฉ๋‹ˆ๋‹ค. + setInputList(prevInputs => { + const updatedInputList = [...prevInputs]; + + // ์ƒˆ๋กœ์šด ์ธ๋ฑ์Šค๋ฅผ inputs ๋ฐฐ์—ด ๊ธธ์ด๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์„ค์ • + const newIndex = updatedInputList[updatedInputList.length - 1].index + 1; + + return [...updatedInputList, {index: newIndex, value: ''}]; + }); + } + }; + + const deleteEmptyInputElementOnBlur = () => { + // 0, 1๋ฒˆ input์ด ๊ฐ’์ด ์žˆ๋Š” ์ƒํƒœ์—์„œ ๋‘ input์˜ ๊ฐ’์„ ๋ชจ๋‘ x๋ฒ„ํŠผ์œผ๋กœ ์ œ๊ฑฐํ•ด๋„ input์ด 2๊ฐœ ๋‚จ์•„์žˆ๋Š” ๋ฌธ์ œ๋ฅผ ์œ„ํ•ด ์กฐ๊ฑด๋ฌธ์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. + if (getFilledInputList().length === 0 && inputList.length > 1) { + setInputList([{index: 0, value: ''}]); + return; + } + + // *ํ‘œ์‹œ ์กฐ๊ฑด๋ฌธ์€ ์ฒ˜์Œ์— input์„ ํด๋ฆญํ–ˆ๋‹ค๊ฐ€ ๋ธ”๋Ÿฌ์‹œ์ผฐ์„ ๋•Œ filledInputList๊ฐ€ ์•„์˜ˆ ์—†์–ด .index์— ์ ‘๊ทผํ•  ๋•Œ ์˜ค๋ฅ˜๊ฐ€ ๋‚ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•œ ์–ผ๋ฆฌ๋ฆฌํ„ด์„ ๋‘์—ˆ์Šต๋‹ˆ๋‹ค. + if (getFilledInputList().length === 0) return; + + if (getFilledInputList().length !== inputList.length) { + setInputList(inputList => { + const filledInputList = getFilledInputList(inputList); + + // ์ƒˆ ์ž…๋ ฅ์˜ ์ธ๋ฑ์Šค๋ฅผ inputs ๊ธธ์ด๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์„ค์ • + const newIndex = filledInputList[filledInputList.length - 1].index + 1; + + return [...filledInputList, {index: newIndex, value: ''}]; + }); + } + }; + + const setInputValueTargetIndex = (index: number, value: string) => { + setInputList(prevInputs => { + const updatedInputList = [...prevInputs]; + const targetInput = findInputByIndex(index, updatedInputList); + + targetInput.value = value; + + return updatedInputList; + }); + }; + + const resetInputValue = () => { + setInputList(initialInputList); + }; + + const focusNextInputOnEnter = (e: React.KeyboardEvent, index: number) => { + if (e.nativeEvent.isComposing) return; + + if (e.key === 'Enter') { + inputRefList.current[index + 1]?.focus(); + } + }; + + const findInputByIndex = (index: number, list?: InputValue[]) => { + return (list ?? inputList).filter(input => input.index === index)[0]; + }; + + const getFilledInputList = (list?: InputValue[]) => { + return (list ?? inputList).filter(({value}) => value.trim().length !== 0); + }; + + const isLastInputFilled = (index: number, value: string) => { + const lastInputIndex = inputList[inputList.length - 1].index; + + return value !== '' && index === lastInputIndex; + }; + + return { + inputList, + inputRefList, + errorMessage, + canSubmit, + errorIndexList, + handleInputChange, + handleChange, + deleteEmptyInputElementOnBlur, + getFilledInputList, + focusNextInputOnEnter, + setInputValueTargetIndex, + resetInputValue, + }; +}; + +export default useDynamicInput; diff --git a/client/src/hooks/useEventLogin.ts b/client/src/hooks/useEventLogin.ts new file mode 100644 index 000000000..ccabe20c1 --- /dev/null +++ b/client/src/hooks/useEventLogin.ts @@ -0,0 +1,42 @@ +import {useState} from 'react'; + +import validateEventPassword from '@utils/validate/validateEventPassword'; + +import RULE from '@constants/rule'; + +import useRequestPostLogin from './queries/useRequestPostLogin'; + +const useEventLogin = () => { + const [password, setPassword] = useState(''); + const [errorMessage, setErrorMessage] = useState(null); + const [canSubmit, setCanSubmit] = useState(false); + const {mutate: postLogin} = useRequestPostLogin(); + + const submitPassword = async (event: React.FormEvent) => { + event.preventDefault(); + + postLogin({password}, {onError: () => setErrorMessage('๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ํ‹€๋ ธ์–ด์š”')}); + }; + + const handleChange = (event: React.ChangeEvent) => { + const newValue = event.target.value; + const validation = validateEventPassword(newValue); + setErrorMessage(validation.errorMessage); + + if (validation.isValid) { + setPassword(newValue); + } + + setCanSubmit(newValue.length === RULE.maxEventPasswordLength); + }; + + return { + password, + errorMessage, + handleChange, + canSubmit, + submitPassword, + }; +}; + +export default useEventLogin; diff --git a/client/src/hooks/useInput.tsx b/client/src/hooks/useInput.tsx new file mode 100644 index 000000000..a6901573b --- /dev/null +++ b/client/src/hooks/useInput.tsx @@ -0,0 +1,97 @@ +import {useEffect, useState} from 'react'; + +import {ValidateResult} from '@utils/validate/type'; + +import {ERROR_MESSAGE} from '@constants/errorMessage'; + +export type InputValue = { + value: string; + index?: number; +}; + +export type UseInputReturn = { + inputList: T[]; + errorMessage: string; + errorIndexList: number[]; + canSubmit: boolean; + handleChange: (index: number, value: string) => void; + setInputList: React.Dispatch>; + addErrorIndex: (index: number) => void; + setCanSubmit: React.Dispatch>; +}; + +type UseInputProps = { + validateFunc: (value: string) => ValidateResult; + initialInputList: T[]; +}; + +const useInput = ({validateFunc, initialInputList}: UseInputProps): UseInputReturn => { + const [inputList, setInputList] = useState(initialInputList); + const [errorMessage, setErrorMessage] = useState(''); + const [errorIndexList, setErrorIndexList] = useState([]); + const [canSubmit, setCanSubmit] = useState(false); + + useEffect(() => { + changeCanSubmit(); + }, [errorMessage, errorIndexList]); + + useEffect(() => { + setInputList(prev => prev.map((value, index) => ({...value, index}))); + }, [inputList.length]); + + const handleChange = (index: number = 0, value: string) => { + const {isValid, errorMessage: validationResultMessage} = validateFunc(value); + + if (validationResultMessage === ERROR_MESSAGE.preventEmpty) { + setErrorMessage(validationResultMessage); + updateInputList(index, value); + addErrorIndex(index); + } else if (isValid && value.length !== 0) { + // TODO: (@soha) ์ฟ ํ‚ค๊ฐ€ ์ž‘์—…ํ•œ errorMessage๋ฅผ ์œ„๋กœ ์˜ฌ๋ฆฌ๊ธฐ ๋ณ€๊ฒฝ ์ถ”ํ›„์— mergeํ›„์— ๋ฐ˜์˜ํ•˜๊ธฐ + setErrorMessage(''); + updateInputList(index, value); + removeErrorIndex(index); + } + }; + + const updateInputList = (index: number, value: string) => { + setInputList(prev => { + const newList = [...prev]; + const targetInput = newList.find(input => input.index === index); + if (targetInput) { + targetInput.value = value; + } + return newList; + }); + }; + + const removeErrorIndex = (index: number) => { + setErrorIndexList(prev => prev.filter(i => i !== index)); + }; + + const addErrorIndex = (index: number) => { + setErrorIndexList(prev => { + if (!prev.includes(index)) { + return [...prev, index]; + } + return prev; + }); + }; + + const changeCanSubmit = () => { + setCanSubmit(errorIndexList.length || errorMessage.length ? false : true); + }; + + return { + inputList, + errorMessage, + errorIndexList, + canSubmit, + handleChange, + setInputList, + addErrorIndex, + setCanSubmit, + }; +}; + +export default useInput; diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx b/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx new file mode 100644 index 000000000..9c9cd80d9 --- /dev/null +++ b/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx @@ -0,0 +1,89 @@ +import type {MemberReportInAction} from 'types/serviceType'; + +import {useEffect, useState} from 'react'; + +import validateMemberReportInAction from '@utils/validate/validateMemberReportInAction'; + +type MemberReportInput = MemberReportInAction & { + index: number; +}; + +type UseMemberReportProps = { + data: MemberReportInAction[]; + addAdjustedMember: (memberReport: MemberReportInAction) => void; + getOnlyOneNotAdjustedRemainMemberIndex: () => number | null; + getIsSamePriceStateAndServerState: () => boolean; + totalPrice: number; +}; + +const useMemberReportInput = ({ + data, + addAdjustedMember, + totalPrice, + getOnlyOneNotAdjustedRemainMemberIndex, + getIsSamePriceStateAndServerState, +}: UseMemberReportProps) => { + const [inputList, setInputList] = useState(data.map((item, index) => ({...item, index}))); + const [canSubmit, setCanSubmit] = useState(false); + + const [canEditList, setCanEditList] = useState([]); + + const onChange = (event: React.ChangeEvent, index: number) => { + const {value} = event.target; + + validateAndAddAdjustedMember(value, index); + }; + + const validateAndAddAdjustedMember = (price: string, index: number) => { + const {isValid} = validateMemberReportInAction(price, totalPrice); + + if (isValid) { + const newInputList = [...inputList]; + newInputList[index].price = Number(price); + setInputList(newInputList); + + const memberReportData: MemberReportInAction = { + name: newInputList[index].name, + price: newInputList[index].price, + isFixed: newInputList[index].isFixed, + }; + addAdjustedMember(memberReportData); + } + }; + + // ์„œ๋ฒ„์™€ ๊ฐ’์ด ๊ฐ™์ง€ ์•Š๊ณ  input price์˜ ์ƒํƒœ๊ฐ€ ๋ชจ๋‘ validํ•˜๋‹ค๋ฉด can submit true + useEffect(() => { + const isSamePriceState = getIsSamePriceStateAndServerState(); + const isAllValid = inputList.every(input => validateMemberReportInAction(String(input.price), totalPrice)); + + setCanSubmit(!isSamePriceState && isAllValid); + }, [inputList]); + + // addAdjustedMember๋กœ ์ธํ•ด data๊ฐ€ ๋ณ€ํ–ˆ์„ ๋•Œ input list์˜ ๊ฐ’์„ ๋งž์ถฐ์ฃผ๊ธฐ ์œ„ํ•จ + useEffect(() => { + setCanSubmit(!getIsSamePriceStateAndServerState()); + setInputList(data.map((item, index) => ({...item, index}))); + + // ๋‚จ์€ ์ธ์›์ด 1๋ช…์ผ ๋•Œ ์ˆ˜์ •์„ ๋ถˆ๊ฐ€๋Šฅํ•˜๋„๋ก ์„ค์ • + const onlyOneIndex = getOnlyOneNotAdjustedRemainMemberIndex(); + + if (data.length !== 0) { + setCanEditList(new Array(data.length).fill(true)); + } + + if (onlyOneIndex !== null) { + const newCanEditList = new Array(data.length).fill(true); + newCanEditList[onlyOneIndex] = false; + setCanEditList(newCanEditList); + } + }, [data]); + + return { + inputList, + onChange, + canEditList, + canSubmit, + }; +}; + +export default useMemberReportInput; diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx new file mode 100644 index 000000000..78c29ee03 --- /dev/null +++ b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx @@ -0,0 +1,327 @@ +import type {MemberReportInAction} from 'types/serviceType'; + +import {renderHook, waitFor, act} from '@testing-library/react'; +import {MemoryRouter} from 'react-router-dom'; +import {QueryClient, QueryClientProvider} from '@tanstack/react-query'; + +import memberReportListInActionJson from '../../mocks/memberReportListInAction.json'; + +import useMemberReportListInAction from './useMemberReportListInAction'; + +describe('useMemberReportListInActionTest', () => { + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: 0, + }, + }, + }); + + const initializeProvider = (actionId: number, totalPrice: number) => + renderHook(() => useMemberReportListInAction(actionId, totalPrice, () => {}), { + wrapper: ({children}) => ( + + {children} + + ), + }); + + const actionId = 123; + const totalPrice = 100000; + + describe('Flow: ์œ ์ €๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๊ฐ’์„ ๋ถˆ๋Ÿฌ์™”์„ ๋•Œ์˜ test', () => { + it('์ดˆ๊ธฐ๊ฐ’์„ ์ •์ƒ์ ์œผ๋กœ ๋ถˆ๋Ÿฌ์˜จ๋‹ค.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + expect(result.current.memberReportListInAction).toStrictEqual(memberReportListInActionJson); + }); + + it('๋ง์ตธ์˜ ๊ฐ€๊ฒฉ์„ 100์›์œผ๋กœ ๋ฐ”๊พธ๋ฉด ๋ง์ตธ์˜ ๊ฐ€๊ฒฉ์€ 100์›์œผ๋กœ ์„ค์ •๋œ๋‹ค.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMember: MemberReportInAction = {name: '๋ง์ตธ', price: 100, isFixed: false}; + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMember); + }); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '๋ง์ตธ'); + + expect(targetMember?.price).toBe(100); + }); + + it('๋ง์ตธ์˜ ๊ฐ€๊ฒฉ์„ 100์›์œผ๋กœ ๋ฐ”๊พธ๋ฉด ๋ง์ตธ์˜ ๊ฐ€๊ฒฉ์€ 100์›์œผ๋กœ ์„ค์ •๋˜๊ณ  ๋‚˜๋จธ์ง€ ์ธ์›์˜ ๊ฐ€๊ฒฉ์ด 33,300์›์œผ๋กœ ์„ค์ •๋œ๋‹ค.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMember: MemberReportInAction = {name: '๋ง์ตธ', price: 100, isFixed: false}; + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMember); + }); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '๋ง์ตธ'); + expect(targetMember?.price).toBe(100); + + const anotherMemberList = result.current.memberReportListInAction.filter(member => member.name !== '๋ง์ตธ'); + + anotherMemberList.forEach(member => { + expect(member.price).toBe(33300); + }); + }); + + it('๋ง์ตธ์˜ ๊ฐ€๊ฒฉ์„ 100์› ์ฟ ํ‚ค์˜ ๊ฐ€๊ฒฉ์„ 100์›์œผ๋กœ ๋ฐ”๊พธ๋ฉด ๋‚˜๋จธ์ง€ ์ธ์›์˜ ๊ฐ€๊ฒฉ์ด 49,900์›์œผ๋กœ ์„ค์ •๋œ๋‹ค.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '๋ง์ตธ', price: 100, isFixed: false}; + const adjustedMemberCookie: MemberReportInAction = {name: '์ฟ ํ‚ค', price: 100, isFixed: true}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + act(() => { + result.current.addAdjustedMember(adjustedMemberCookie); + }); + + const anotherMemberList = result.current.memberReportListInAction.filter( + member => !(member.name === '๋ง์ตธ' || member.name === '์ฟ ํ‚ค'), + ); + + anotherMemberList.forEach(member => { + expect(member.price).toBe(49900); + }); + }); + + it('๋ง์ตธ์˜ ๊ฐ€๊ฒฉ์„ 100์› ์ฟ ํ‚ค์˜ ๊ฐ€๊ฒฉ์„ 100์›์œผ๋กœ ๋ฐ”๊พธ๋ฉด ๋‚˜๋จธ์ง€ ์ธ์›์˜ ๊ฐ€๊ฒฉ์ด 49,900์›์œผ๋กœ ์„ค์ •๋œ๋‹ค.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '๋ง์ตธ', price: 100, isFixed: false}; + const adjustedMemberCookie: MemberReportInAction = {name: '์ฟ ํ‚ค', price: 100, isFixed: false}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + act(() => { + result.current.addAdjustedMember(adjustedMemberCookie); + }); + + const anotherMemberList = result.current.memberReportListInAction.filter( + member => !(member.name === '๋ง์ตธ' || member.name === '์ฟ ํ‚ค'), + ); + + anotherMemberList.forEach(member => { + expect(member.price).toBe(49900); + }); + }); + + it('๋ง์ตธ์˜ ๊ฐ€๊ฒฉ์„ 100์›์œผ๋กœ ๋ฐ”๊พธ๊ณ  ๋‹ค์‹œ ๋ง์ตธ์˜ ๊ฐ€๊ฒฉ์„ 10,000์›์œผ๋กœ ๋ฐ”๊พธ๋ฉด ๋‚˜๋จธ์ง€ ์ธ์›์˜ ๊ฐ€๊ฒฉ์ด 30,000์›์œผ๋กœ ์„ค์ •๋œ๋‹ค.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '๋ง์ตธ', price: 100, isFixed: false}; + const adjustedMemberMangchoAfter: MemberReportInAction = {name: '๋ง์ตธ', price: 10000, isFixed: true}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangchoAfter); + }); + + const anotherMemberList = result.current.memberReportListInAction.filter(member => member.name !== '๋ง์ตธ'); + + anotherMemberList.forEach(member => { + expect(member.price).toBe(30000); + }); + }); + }); + + describe('์˜ˆ์™ธ & ์—ฃ์ง€์ผ€์ด์Šค', () => { + it('๋™์ผํ•œ ์ธ์›์˜ ๊ฐ€๊ฒฉ์„ ๋™์ผํ•˜๊ฒŒ ๋ฐ”๊พธ๋ฉด ๋ณ€ํ•จ์—†๋‹ค.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '๋ง์ตธ', price: 100, isFixed: false}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + act(() => { + result.current.addAdjustedMember({...adjustedMemberMangcho, isFixed: true}); + }); + + const anotherMemberList = result.current.memberReportListInAction.filter(member => member.name !== '๋ง์ตธ'); + + expect(anotherMemberList[0].price).toBe(33300); + }); + + it('๋ง์ตธ์—๊ฒŒ 300์›์„ ์ฃผ๋ฉด ๋‚˜๋จธ์ง€ ์‚ฌ๋žŒ๋“ค์€ 33233์›์ด๊ณ  ๋งˆ์ง€๋ง‰ ์‚ฌ๋žŒ์€ 33234์›์ด ๋œ๋‹ค.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '๋ง์ตธ', price: 300, isFixed: false}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '๋ง์ตธ'); + expect(targetMember?.price).toBe(300); + + const anotherMemberList = result.current.memberReportListInAction.filter( + member => member.name === '์ด์ƒ' || member.name === '์†Œํ•˜', + ); + + anotherMemberList.forEach(member => { + expect(member.price).toBe(33233); + }); + + const lastMember = result.current.memberReportListInAction.find(member => member.name === '์ฟ ํ‚ค'); + + expect(lastMember?.price).toBe(33234); + }); + + it('๋ง์ตธ, ์ฟ ํ‚ค์˜ ๊ฐ€๊ฒฉ์„ 100์›์œผ๋กœ ๋ฐ”๊พผ ํ›„ ๋‹ค์‹œ ์ฟ ํ‚ค์˜ ๊ฐ€๊ฒฉ์„ 33000์›์œผ๋กœ ๋ฐ”๊พธ๋ฉด ์ฟ ํ‚ค์˜ isFixed๋Š” false๊ฐ€ ๋œ๋‹ค.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '๋ง์ตธ', price: 100, isFixed: false}; + const adjustedMemberCookie: MemberReportInAction = {name: '์ฟ ํ‚ค', price: 100, isFixed: false}; + const adjustedMemberCookieReset: MemberReportInAction = {name: '์ฟ ํ‚ค', price: 33300, isFixed: true}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + act(() => { + result.current.addAdjustedMember(adjustedMemberCookie); + }); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '์ฟ ํ‚ค'); + + expect(targetMember?.isFixed).toBe(true); + + act(() => { + result.current.addAdjustedMember(adjustedMemberCookieReset); + }); + + const targetMemberReset = result.current.memberReportListInAction.find(member => member.name === '์ฟ ํ‚ค'); + + expect(targetMemberReset?.isFixed).toBe(false); + }); + + it('๋ง์ตธ์˜ ๊ฐ€๊ฒฉ์„ 100์›์œผ๋กœ ๋ฐ”๊พผ ํ›„ ๋‹ค์‹œ ๋ง์ตธ์˜ ๊ฐ€๊ฒฉ์„ 25000์›์œผ๋กœ ๋ฐ”๊พธ๋ฉด ๋ง์ตธ์˜ isFixed๋Š” false๊ฐ€ ๋œ๋‹ค.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '๋ง์ตธ', price: 100, isFixed: false}; + const adjustedMemberMangchoAfter: MemberReportInAction = {name: '๋ง์ตธ', price: 25000, isFixed: true}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '๋ง์ตธ'); + expect(targetMember?.isFixed).toBe(true); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangchoAfter); + }); + + const targetMemberReset = result.current.memberReportListInAction.find(member => member.name === '๋ง์ตธ'); + expect(targetMemberReset?.isFixed).toBe(false); + }); + + it('์•„๋ฌด๋„ ์กฐ์ •๋œ ๊ฐ’์ด ์—†๋‹ค๋ฉด ์กฐ์ •๊ฐ’์ด ์žˆ๋Š”์ง€ ํ™•์ธ ๊ฒฐ๊ณผ false๋‹ค.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + expect(result.current.isExistAdjustedPrice()).toBe(false); + }); + + it('๋ง์ตธ์˜ ๊ฐ€๊ฒฉ์„ 100์›์œผ๋กœ ๋ฐ”๊พผ ํ›„ ๋ฆฌ์ŠคํŠธ ์ค‘ ์กฐ์ •๊ฐ’์ด ์žˆ๋Š”์ง€ ํ™•์ธ ๊ฒฐ๊ณผ true๋‹ค.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '๋ง์ตธ', price: 100, isFixed: false}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + expect(result.current.isExistAdjustedPrice()).toBe(true); + }); + }); + + describe('์ง€์ถœ ์ธ์›์ด 2๋ช…์ธ ์ƒํ™ฉ', () => { + const actionId = 1; + const totalPrice = 50000; + + // ๋ง์ตธ ์ด์ƒ + it('๋ง์ตธ์˜ ๊ฐ€๊ฒฉ์„ 100์›์œผ๋กœ ์ˆ˜์ •ํ•œ ๊ฒฝ์šฐ, ์ด์ƒ์˜ ๊ฐ€๊ฒฉ์ด 49900์›์œผ๋กœ ์ˆ˜์ •๋œ๋‹ค.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '๋ง์ตธ', price: 100, isFixed: false}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '์ด์ƒ'); + + expect(targetMember?.price).toBe(49900); + }); + + it('๋ง์ตธ์˜ ๊ฐ€๊ฒฉ์„ 100์›์œผ๋กœ ์ˆ˜์ •ํ•˜๊ณ  ๋‹ค์‹œ 200์›์œผ๋กœ ์ˆ˜์ •ํ•œ ๊ฒฝ์šฐ, ์ด์ƒ์˜ ๊ฐ€๊ฒฉ์ด 49800์›์œผ๋กœ ์ˆ˜์ •๋œ๋‹ค.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '๋ง์ตธ', price: 100, isFixed: false}; + const adjustedMemberMangchoOther: MemberReportInAction = {name: '๋ง์ตธ', price: 200, isFixed: true}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangchoOther); + }); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '์ด์ƒ'); + + expect(targetMember?.price).toBe(49800); + }); + }); + + // last + describe('onSubmit ์‹คํ–‰ ์‹œ ๋ฐ˜์˜ ํ…Œ์ŠคํŠธ', () => { + it('๋ง์ตธ์˜ ๊ฐ€๊ฒฉ์„ 100์›์œผ๋กœ ๋ฐ”๊พธ๊ณ  ์ €์žฅํ•˜๋ฉด ๋ง์ตธ 100์›์ด ๋ฐ˜์˜๋œ๋‹ค.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '๋ง์ตธ', price: 100, isFixed: false}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + await waitFor(() => { + result.current.onSubmit(); + }); + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '๋ง์ตธ'); + expect(targetMember?.price).toBe(100); + }); + }); +}); diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts new file mode 100644 index 000000000..0e32d740c --- /dev/null +++ b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts @@ -0,0 +1,156 @@ +import type {MemberReportInAction} from 'types/serviceType'; + +import {useEffect, useState} from 'react'; + +import useRequestGetMemberReportListInAction from '@hooks/queries/useRequestGetMemberReportListInAction'; +import useRequestPutMemberReportListInAction from '@hooks/queries/useRequestPutMemberReportListInAction'; + +const useMemberReportListInAction = (actionId: number, totalPrice: number, onClose: () => void) => { + const {memberReportListInActionFromServer, queryResult} = useRequestGetMemberReportListInAction(actionId); + const {putMemberReportListInAction} = useRequestPutMemberReportListInAction(actionId); + + const [memberReportListInAction, setMemberReportListInAction] = useState( + memberReportListInActionFromServer, + ); + + // isFixed๋ฅผ ๋ชจ๋‘ ํ’€๊ณ  ๊ณ„์‚ฐ๊ฐ’์œผ๋กœ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ + const reCalculatePriceByTotalPriceChange = () => { + const {divided, remainder} = calculateDividedPrice(memberReportListInAction.length, 0); + + const resetMemberReportList = [...memberReportListInAction]; + resetMemberReportList.forEach((member, index) => { + if (index !== resetMemberReportList.length - 1) { + member.price = divided; + } else { + member.price = divided + remainder; + } + member.isFixed = false; + }); + + setMemberReportListInAction(resetMemberReportList); + }; + + // ์ด ๊ธˆ์•ก์ด ๋ณ€๋™๋์„ ๋•Œ (์„œ๋ฒ„์—์„œ ์˜จ ๊ฐ’๊ณผ ๋‹ค๋ฅผ ๋•Œ) ์žฌ๊ณ„์‚ฐ ์‹คํ–‰ + useEffect(() => { + const totalPriceFromServer = memberReportListInActionFromServer.reduce((acc, cur) => acc + cur.price, 0); + + if (totalPriceFromServer !== totalPrice && totalPriceFromServer !== 0) { + reCalculatePriceByTotalPriceChange(); + } + }, [totalPrice, memberReportListInActionFromServer]); + + useEffect(() => { + if (queryResult.isSuccess) { + setMemberReportListInAction(memberReportListInActionFromServer); + } + }, [memberReportListInActionFromServer, queryResult.isSuccess]); + + const isExistAdjustedPrice = () => { + return memberReportListInAction.some(member => member.isFixed === true); + }; + + // ์กฐ์ •๋˜์ง€ ์•Š์€ ์ธ์›์ด ๋‹จ 1๋ช…์ธ ๊ฒฝ์šฐ์˜ index + const getOnlyOneNotAdjustedRemainMemberIndex = (): number | null => { + const adjustedPriceCount = getAdjustedMemberCount(memberReportListInAction); + + if (adjustedPriceCount < memberReportListInAction.length - 1) return null; + + return memberReportListInAction.findIndex(member => member.isFixed === false); + }; + + // ์กฐ์ •๊ฐ’ ๋ฉค๋ฒ„์˜ ์ˆ˜๋ฅผ ๊ตฌํ•˜๋Š” ํ•จ์ˆ˜ + const getAdjustedMemberCount = (memberReportListInAction: MemberReportInAction[]) => { + return memberReportListInAction.filter(member => member.isFixed === true).length; + }; + + const addAdjustedMember = (memberReport: MemberReportInAction) => { + const newMemberReportListInAction = memberReportListInAction.map(member => + member.name === memberReport.name ? {...member, price: memberReport.price, isFixed: true} : member, + ); + + calculateAnotherMemberPrice(newMemberReportListInAction); + }; + + const calculateDividedPrice = (remainMemberCount: number, totalAdjustedPrice: number) => { + return { + divided: Math.floor((totalPrice - totalAdjustedPrice) / remainMemberCount), + remainder: (totalPrice - totalAdjustedPrice) % remainMemberCount, + }; + }; + + // ๊ณ„์‚ฐ๊ฐ’์œผ๋กœ ๊ฐ’์„ ๋ณ€๊ฒฝํ–ˆ์„ ๋•Œ isFixed๋ฅผ ํ‘ธ๋Š” ํ•จ์ˆ˜ + // 100 true 33300 true 33300 false 33300 false + const setIsFixedFalseAtResetToDividedPrice = (memberReportListInAction: MemberReportInAction[], divided: number) => { + return memberReportListInAction.map(memberReport => { + if (memberReport.isFixed === true && memberReport.price === divided) { + return {...memberReport, isFixed: false}; + } + + return memberReport; + }); + }; + + const calculateAnotherMemberPrice = (memberReportListInAction: MemberReportInAction[]) => { + // ์ด ์กฐ์ •์น˜ ๊ธˆ์•ก + const totalAdjustedPrice = memberReportListInAction + .filter(memberReport => memberReport.isFixed === true) + .reduce((acc, cur) => acc + cur.price, 0); + + const remainMemberCount = memberReportListInAction.length - getAdjustedMemberCount(memberReportListInAction); + const {divided, remainder} = calculateDividedPrice(remainMemberCount, totalAdjustedPrice); + + const updatedList = memberReportListInAction.map(member => + member.isFixed === true ? member : {...member, price: divided}, + ); + + // ๋‚˜๋จธ์ง€๋ฅผ ์กฐ์ •๋˜์ง€ ์•Š์€ ๋ฉค๋ฒ„ ์ค‘ ๋งˆ์ง€๋ง‰ ๋ฉค๋ฒ„์—๊ฒŒ ์ถ”๊ฐ€ + if (remainder !== 0) { + const nonAdjustedMembers = updatedList.filter(member => member.isFixed === false); + const lastNonAdjustedMemberIndex = updatedList.findIndex( + member => member.name === nonAdjustedMembers[nonAdjustedMembers.length - 1].name, + ); + + if (lastNonAdjustedMemberIndex !== -1) { + updatedList[lastNonAdjustedMemberIndex].price += remainder; + } + } + + // ์กฐ์ •๋์ง€๋งŒ ๊ณ„์‚ฐ๊ฐ’์œผ๋กœ ๊ฐ€๊ฒฉ์ด ๋ณ€ํ•œ ๊ฒฝ์šฐ fixed ์ƒํƒœ๋ฅผ ํ’€์–ด์•ผํ•œ๋‹ค. + const result = setIsFixedFalseAtResetToDividedPrice(updatedList, divided); + setMemberReportListInAction(result); + }; + + const onSubmit = () => { + putMemberReportListInAction(memberReportListInAction); + + onClose(); + }; + + const getIsSamePriceStateAndServerState = () => { + const serverStatePriceList = memberReportListInActionFromServer.map(({price}) => price); + const clientStatePriceList = memberReportListInAction.map(({price}) => price); + + let isSame = true; + + // isArrayEqual์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์€ ์ด์œ ๋Š” ์ •๋ ฌ์ด ์˜ํ–ฅ์„ ๋ฐ›์œผ๋ฉด ์•ˆ ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค + for (let i = 0; i < serverStatePriceList.length; i++) { + if (serverStatePriceList[i] !== clientStatePriceList[i]) { + isSame = false; + } + } + + return isSame; + }; + + return { + memberReportListInAction, + addAdjustedMember, + isExistAdjustedPrice, + onSubmit, + getOnlyOneNotAdjustedRemainMemberIndex, + getIsSamePriceStateAndServerState, + queryResult, + }; +}; + +export default useMemberReportListInAction; diff --git a/client/src/hooks/useNavSwitch.tsx b/client/src/hooks/useNavSwitch.tsx new file mode 100644 index 000000000..a622a7a30 --- /dev/null +++ b/client/src/hooks/useNavSwitch.tsx @@ -0,0 +1,42 @@ +import {useEffect, useState} from 'react'; +import {useLocation, useNavigate} from 'react-router-dom'; + +const PATH_TABLE: Record = { + ํ™ˆ: 'home', + ๊ด€๋ฆฌ: 'admin', +}; + +const PATH_DISPLAY_TABLE: Record = { + home: 'ํ™ˆ', + admin: '๊ด€๋ฆฌ', +}; + +const useNavSwitch = () => { + const paths = ['ํ™ˆ', '๊ด€๋ฆฌ']; + const location = useLocation(); + const navigate = useNavigate(); + + const pathArray = location.pathname.split('/'); + const basePath = pathArray.slice(0, -1).join('/'); + const lastPath = pathArray[pathArray.length - 1]; + + const [nav, setNav] = useState(PATH_DISPLAY_TABLE[lastPath]); + + useEffect(() => { + const isLogin = lastPath === 'login'; + setNav(isLogin ? '๊ด€๋ฆฌ' : PATH_DISPLAY_TABLE[lastPath]); + }, [location]); + + const onChange = (displayName: string) => { + setNav(displayName); + navigate(`${basePath}/${PATH_TABLE[displayName]}`); + }; + + return { + nav, + paths, + onChange, + }; +}; + +export default useNavSwitch; diff --git a/client/src/hooks/usePutAndDeleteBillAction.ts b/client/src/hooks/usePutAndDeleteBillAction.ts new file mode 100644 index 000000000..6f1e4feaf --- /dev/null +++ b/client/src/hooks/usePutAndDeleteBillAction.ts @@ -0,0 +1,113 @@ +import type {Bill, BillInputType, InputPair} from 'types/serviceType'; + +import {useEffect, useState} from 'react'; + +import {ValidateResult} from '@utils/validate/type'; + +import {ERROR_MESSAGE} from '@constants/errorMessage'; + +import usePutBillAction from './queries/useRequestPutBillAction'; +import useDeleteBillAction from './queries/useRequestDeleteBillAction'; + +const usePutAndDeleteBillAction = ( + initialValue: InputPair, + validateFunc: (inputPair: Bill) => ValidateResult, + onClose: () => void, +) => { + const [inputPair, setInputPair] = useState(initialValue); + const [canSubmit, setCanSubmit] = useState(false); + const [errorInfo, setErrorInfo] = useState>({title: false, price: false}); + const [errorMessage, setErrorMessage] = useState(null); + + const {mutateAsync: putBillAction} = usePutBillAction(); + const {mutate: deleteBillAction} = useDeleteBillAction(); + + // ํ˜„์žฌ ํƒ€๊ฒŸ์˜ event.target.value๋ฅผ ๋„ฃ์–ด์ฃผ๊ธฐ ์œ„ํ•ด์„œ + const getFieldValue = (field: BillInputType, value: string) => { + if (field === 'title') { + return {title: value, price: Number(inputPair.price)}; + } else { + return {title: inputPair.title, price: Number(value)}; + } + }; + + // TODO: (@weadie) getFieldValue ๋ฅผ ๋ฆฌํŽ™ํ† ๋งํ•ด์•ผํ•œ๋‹ค. + + const handleInputChange = (field: BillInputType, event: React.ChangeEvent) => { + const {value} = event.target; + + const {isValid, errorMessage, errorInfo} = validateFunc(getFieldValue(field, value)); + + setErrorMessage(errorMessage); + + if (isValid) { + // valid์ผ ๊ฒฝ์šฐ ์—๋Ÿฌ๋ฉ”์‹œ์ง€ nope, setValue, submit์€ value๊ฐ€ ๋น„์ง€ ์•Š์•˜์„ ๋•Œ true๋ฅผ ์„ค์ • + setInputPair(prevInputPair => { + return { + ...prevInputPair, + [field]: value, + }; + }); + setCanSubmit(value.length !== 0); + } else { + const {isValid: isValidName} = validateFunc(getFieldValue('title', inputPair.title)); + const {isValid: isValidPrice} = validateFunc(getFieldValue('price', inputPair.price)); + + setCanSubmit(isValidName && isValidPrice); + // validํ•˜์ง€ ์•Š์œผ๋ฉด event.target.value ๋ฎ์–ด์“ฐ๊ธฐ + event.target.value = inputPair[field]; + } + + if (field === 'title') { + // ํ˜„์žฌ field๊ฐ€ title์ผ ๋•Œ๋Š” title์˜ errorInfo๋งŒ ๋ฐ˜์˜ํ•ด์คŒ (blur์—์„œ๋„ errorInfo๋ฅผ ์กฐ์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ) + setErrorInfo(prev => ({title: errorInfo?.title ?? false, price: prev.price})); + } else { + setErrorInfo(prev => ({title: prev.title, price: errorInfo?.price ?? false})); + } + }; + + const handleOnBlur = () => { + const {isValid, errorMessage, errorInfo} = validateFunc({title: inputPair.title, price: Number(inputPair.price)}); + + // blur์‹œ ๊ฐ’์ด ๋น„์—ˆ์„ ๋•Œ error state ๋ฐ˜์˜ + if (inputPair.price.length === 0 || inputPair.title.length === 0) { + setErrorMessage(ERROR_MESSAGE.preventEmpty); + setErrorInfo({title: inputPair.title.length === 0, price: inputPair.price.length === 0}); + setCanSubmit(false); + return; + } + + // ์ด์™ธ blur์‹œ์— ์ถ”๊ฐ€๋กœ ๊ฒ€์ฆํ•จ + setErrorMessage(errorMessage); + setCanSubmit(isValid); + setErrorInfo(errorInfo ?? {title: false, price: false}); + }; + + const onSubmit = async (event: React.FormEvent, inputPair: InputPair, actionId: number) => { + event.preventDefault(); + + const {title, price} = inputPair; + + await putBillAction({actionId, title, price: Number(price)}); + + onClose(); + }; + + const onDelete = async (actionId: number) => { + deleteBillAction({actionId}); + onClose(); + }; + + return { + inputPair, + handleInputChange, + handleOnBlur, + onSubmit, + onDelete, + canSubmit, + errorMessage, + errorInfo, + }; +}; + +export default usePutAndDeleteBillAction; diff --git a/client/src/hooks/useSearchInMemberList.ts b/client/src/hooks/useSearchInMemberList.ts new file mode 100644 index 000000000..09f227b8e --- /dev/null +++ b/client/src/hooks/useSearchInMemberList.ts @@ -0,0 +1,54 @@ +import {useState} from 'react'; + +import useRequestGetCurrentInMemberList from './queries/useRequestGetCurrentInMemberList'; + +export type ReturnUseSearchInMemberList = { + currentInputIndex: number; + handleCurrentInputIndex: (inputIndex: number) => void; + filteredInMemberList: string[]; + searchCurrentInMember: (event: React.ChangeEvent) => void; + chooseMember: (inputIndex: number, name: string) => void; +}; + +const useSearchInMemberList = (handleChange: (index: number, value: string) => void): ReturnUseSearchInMemberList => { + const [currentInputIndex, setCurrentInputIndex] = useState(-1); + + // ์„œ๋ฒ„์—์„œ ๊ฐ€์ ธ์˜จ ์ „์ฒด ๋ฆฌ์ŠคํŠธ + const {data} = useRequestGetCurrentInMemberList(); + const currentInMemberList = data?.memberNames ?? []; + + // ๊ฒ€์ƒ‰๋œ ๋ฆฌ์ŠคํŠธ (๋”ฐ๋กœ ๋‘” ์ด์œ ๋Š” ๊ฒ€์ƒ‰ ํ›„ ํด๋ฆญํ–ˆ์„ ๋•Œ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋น„์›Œ์ฃผ์–ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ) + const [filteredInMemberList, setFilteredInMemberList] = useState>([]); + + const filterMatchItems = (keyword: string) => { + if (keyword.trim() === '') return []; + + return currentInMemberList + .filter(member => member.toLocaleLowerCase().indexOf(keyword.toLocaleLowerCase()) > -1) + .slice(0, 3); + }; + + const chooseMember = (inputIndex: number, name: string) => { + setFilteredInMemberList([]); + handleChange(inputIndex, name); + }; + + const searchCurrentInMember = (event: React.ChangeEvent) => { + const {value} = event.target; + setFilteredInMemberList(filterMatchItems(value)); + }; + + const handleCurrentInputIndex = (inputIndex: number) => { + setCurrentInputIndex(inputIndex); + }; + + return { + currentInputIndex, + handleCurrentInputIndex, + filteredInMemberList, + searchCurrentInMember, + chooseMember, + }; +}; + +export default useSearchInMemberList; diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx new file mode 100644 index 000000000..90782cbdf --- /dev/null +++ b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx @@ -0,0 +1,41 @@ +import {renderHook, waitFor} from '@testing-library/react'; +import {MemoryRouter} from 'react-router-dom'; + +import AppErrorBoundary from '@components/AppErrorBoundary/ErrorCatcher'; +import QueryClientBoundary from '@components/QueryClientBoundary/QueryClientBoundary'; +import {ToastProvider} from '@hooks/useToast/ToastProvider'; + +import reportListJson from '../../mocks/reportList.json'; + +import useSearchMemberReportList from './useSearchMemberReportList'; + +describe('useSearchMemberReportList', () => { + const initializeProvider = (name: string) => + renderHook(() => useSearchMemberReportList({name}), { + wrapper: ({children}) => ( + + + + {children} + + + + ), + }); + + it('๋นˆ ๊ฐ’์„ ๊ฒ€์ƒ‰ํ•œ๋‹ค๋ฉด ๊ฒ€์ƒ‰ ๋ชฉ๋ก์€ ๋น„์–ด์žˆ๋‹ค.', async () => { + const {result} = initializeProvider(''); + + await waitFor(() => expect(result.current.memberReportSearchList).toStrictEqual(reportListJson)); + }); + + it('๊ฒ€์ƒ‰์–ด์˜ ์ผ๋ถ€์™€ ์ผ์น˜ํ•˜๋Š” ์ด๋ฆ„์ด ์žˆ๋‹ค๋ฉด ํ•ด๋‹น ์ด๋ฆ„์„ ๋ชฉ๋ก์— ๋ฐ˜ํ™˜ํ•œ๋‹ค.', async () => { + const keyword = '์†Œ'; + const {result} = initializeProvider(keyword); + const expectedMemberReportSearchList = reportListJson.filter(memberReport => memberReport.name.includes(keyword)); + + await waitFor(() => { + expect(result.current.memberReportSearchList).toStrictEqual(expectedMemberReportSearchList); + }); + }); +}); diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx new file mode 100644 index 000000000..4a967e45c --- /dev/null +++ b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx @@ -0,0 +1,16 @@ +import useRequestGetMemberReportList from '@hooks/queries/useRequestGetMemberReportList'; + +type UseSearchMemberReportListParams = { + name: string; +}; + +const useSearchMemberReportList = ({name}: UseSearchMemberReportListParams) => { + const {data} = useRequestGetMemberReportList(); + const memberReportList = data ?? []; + + return { + memberReportSearchList: memberReportList.filter(memberReport => memberReport.name.includes(name)), + }; +}; + +export default useSearchMemberReportList; diff --git a/client/src/hooks/useSetAllMemberList.tsx b/client/src/hooks/useSetAllMemberList.tsx new file mode 100644 index 000000000..02241d3e3 --- /dev/null +++ b/client/src/hooks/useSetAllMemberList.tsx @@ -0,0 +1,100 @@ +import {useEffect, useState} from 'react'; + +import {ValidateResult} from '@utils/validate/type'; +import {MemberChange} from '@apis/request/member'; + +import isArraysEqual from '@utils/isArraysEqual'; + +import useDeleteAllMemberList from './queries/useRequestDeleteAllMemberList'; +import usePutAllMemberList from './queries/useRequestPutAllMemberList'; +import useInput from './useInput'; + +interface UseSetAllMemberListProps { + validateFunc: (name: string) => ValidateResult; + allMemberList: string[]; + handleCloseAllMemberListModal: () => void; +} + +interface UseSetAllMemberListReturns { + editedAllMemberList: string[]; + canSubmit: boolean; + errorMessage: string; + errorIndexList: number[]; + handleNameChange: (index: number, event: React.ChangeEvent) => void; + handleClickDeleteButton: (index: number) => Promise; + handlePutAllMemberList: () => Promise; +} + +const useSetAllMemberList = ({ + validateFunc, + allMemberList, + handleCloseAllMemberListModal, +}: UseSetAllMemberListProps): UseSetAllMemberListReturns => { + const initialInputList = allMemberList.map((name, index) => ({index, value: name})); + const { + inputList, + errorMessage, + errorIndexList, + canSubmit, + handleChange, + setInputList: setEditedAllMemberList, + setCanSubmit, + } = useInput({validateFunc, initialInputList}); + + const [deleteInOriginal, setDeleteInOriginal] = useState(allMemberList); + const [deleteMemberList, setDeleteMemberList] = useState([]); + + const {mutateAsync: deleteAllMemberList} = useDeleteAllMemberList(); + const {mutate: putAllMemberList} = usePutAllMemberList(); + + const editedAllMemberList = inputList.map(input => input.value); + + useEffect(() => { + setCanSubmit(!isArraysEqual(editedAllMemberList, allMemberList)); + }, [editedAllMemberList]); + + const handleNameChange = (index: number, event: React.ChangeEvent) => { + const {value} = event.target; + + handleChange(index, value); + }; + + const handleClickDeleteButton = async (index: number) => { + const memberToDelete = editedAllMemberList[index]; + + setDeleteMemberList(prev => [...prev, memberToDelete]); + setDeleteInOriginal(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); + setEditedAllMemberList(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); + }; + + const handlePutAllMemberList = async () => { + // deleteMemberList๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋งŒ ๋ฐ˜๋ณต๋ฌธ ์‹คํ–‰ (์‚ญ์ œ api ์š”์ฒญ) + if (deleteMemberList.length > 0) { + for (const deleteMember of deleteMemberList) { + await deleteAllMemberList({memberName: deleteMember}); + } + } + + const editedMemberName: MemberChange[] = deleteInOriginal + .map((originalName, index) => { + if (editedAllMemberList[index] !== originalName) { + return {before: originalName, after: editedAllMemberList[index]}; + } + return null; // ์กฐ๊ฑด์— ๋งž์ง€ ์•Š์œผ๋ฉด null์„ ๋ฐ˜ํ™˜ + }) + .filter(item => item !== null); // null์ธ ํ•ญ๋ชฉ์„ ํ•„ํ„ฐ๋งํ•˜์—ฌ ์ œ๊ฑฐ + if (!isArraysEqual(editedAllMemberList, deleteInOriginal)) putAllMemberList({members: editedMemberName}); + handleCloseAllMemberListModal(); + }; + + return { + editedAllMemberList, + canSubmit, + errorMessage, + errorIndexList, + handleNameChange, + handleClickDeleteButton, + handlePutAllMemberList, + }; +}; +export default useSetAllMemberList; diff --git a/client/src/hooks/useSetBillInput.ts b/client/src/hooks/useSetBillInput.ts new file mode 100644 index 000000000..a14b2a481 --- /dev/null +++ b/client/src/hooks/useSetBillInput.ts @@ -0,0 +1,67 @@ +import {useState} from 'react'; + +import validatePurchase from '@utils/validate/validatePurchase'; +import {Bill, BillInputType} from 'types/serviceType'; + +import useRequestPostBillList from './queries/useRequestPostBillList'; + +interface UseSetBillInputProps { + setIsAddEditableItem: React.Dispatch>; +} + +interface UseSetBillInputReturns { + billInput: Bill; + handleChangeBillInput: (field: BillInputType, event: React.ChangeEvent) => void; + handleBlurBillRequest: () => void; +} + +const useSetBillInput = ({setIsAddEditableItem}: UseSetBillInputProps): UseSetBillInputReturns => { + const initialInput = {title: '', price: 0}; + const [billInput, setBillInput] = useState(initialInput); + + const {mutate: postBillList} = useRequestPostBillList(); + + const handleChangeBillInput = (field: BillInputType, event: React.ChangeEvent) => { + const {value} = event.target; + const {isValid} = validatePurchase({ + ...billInput, + [field]: value, + }); + + if (isValid) { + setBillInput(prev => ({ + ...prev, + [field]: value, + })); + } + }; + + const handleBlurBillRequest = () => { + const isEmptyTitle = billInput.title.trim().length; + const isEmptyPrice = Number(billInput.price); + + // ๋‘ input์˜ ๊ฐ’์ด ๋ชจ๋‘ ์ฑ„์›Œ์กŒ์„ ๋•Œ api ์š”์ฒญ + // api ์š”์ฒญ์„ ํ•˜๋ฉด Input์„ ๋„์šฐ์ง€ ์•Š์Œ + if (isEmptyTitle && isEmptyPrice) { + postBillList( + {billList: [billInput]}, + { + onSuccess: () => { + setBillInput(initialInput); + setIsAddEditableItem(false); + }, + }, + ); + } else if (!isEmptyTitle && !isEmptyPrice) { + setIsAddEditableItem(false); + } + }; + + return { + billInput, + handleBlurBillRequest, + handleChangeBillInput, + }; +}; + +export default useSetBillInput; diff --git a/client/src/hooks/useSetEventNamePage.ts b/client/src/hooks/useSetEventNamePage.ts new file mode 100644 index 000000000..f5b5bce12 --- /dev/null +++ b/client/src/hooks/useSetEventNamePage.ts @@ -0,0 +1,32 @@ +import {useState} from 'react'; + +import validateEventName from '@utils/validate/validateEventName'; + +const useSetEventNamePage = () => { + const [eventName, setEventName] = useState(''); + const [errorMessage, setErrorMessage] = useState(null); + const [canSubmit, setCanSubmit] = useState(false); + + const handleEventNameChange = (event: React.ChangeEvent) => { + const newValue = event.target.value; + const validation = validateEventName(newValue); + + setCanSubmit(newValue.length !== 0); + setErrorMessage(validation.errorMessage); + + if (validation.isValid) { + setEventName(newValue); + } else { + event.target.value = eventName; + } + }; + + return { + eventName, + errorMessage, + canSubmit, + handleEventNameChange, + }; +}; + +export default useSetEventNamePage; diff --git a/client/src/hooks/useSetEventPasswordPage.ts b/client/src/hooks/useSetEventPasswordPage.ts new file mode 100644 index 000000000..82ca72fb1 --- /dev/null +++ b/client/src/hooks/useSetEventPasswordPage.ts @@ -0,0 +1,60 @@ +import {useEffect, useState} from 'react'; +import {useLocation, useNavigate} from 'react-router-dom'; + +import validateEventPassword from '@utils/validate/validateEventPassword'; + +import {ROUTER_URLS} from '@constants/routerUrls'; +import RULE from '@constants/rule'; + +import usePostEvent from './queries/useRequestPostEvent'; + +const useSetEventPasswordPage = () => { + const [eventName, setEventName] = useState(''); + const [password, setPassword] = useState(''); + const [errorMessage, setErrorMessage] = useState(''); + const [canSubmit, setCanSubmit] = useState(false); + const navigate = useNavigate(); + const location = useLocation(); + const {mutate: postEvent, isPending: isPostEventPending} = usePostEvent(); + + useEffect(() => { + if (!location.state) { + navigate(ROUTER_URLS.main); + } else { + setEventName(location.state.eventName); + } + }, []); + + const submitPassword = async (event: React.FormEvent) => { + event.preventDefault(); + + postEvent( + {eventName, password: parseInt(password)}, + { + onSuccess: data => { + navigate(`${ROUTER_URLS.eventCreateComplete}?${new URLSearchParams({eventId: data.eventId})}`, { + replace: true, + }); + }, + }, + ); + }; + + const handleChange = (event: React.ChangeEvent) => { + const newValue = event.target.value; + const validation = validateEventPassword(newValue); + + setCanSubmit(newValue.length === RULE.maxEventPasswordLength); + + if (validation.isValid) { + setPassword(newValue); + setErrorMessage(''); + } else { + event.target.value = password; + setErrorMessage(validation.errorMessage ?? ''); + } + }; + + return {submitPassword, errorMessage, password, handleChange, canSubmit, isPostEventPending}; +}; +export default useSetEventPasswordPage; diff --git a/client/src/hooks/useToast/ToastProvider.tsx b/client/src/hooks/useToast/ToastProvider.tsx new file mode 100644 index 000000000..be0d2ea15 --- /dev/null +++ b/client/src/hooks/useToast/ToastProvider.tsx @@ -0,0 +1,47 @@ +/** @jsxImportSource @emotion/react */ +import {createContext, useEffect, useState} from 'react'; + +import {ToastProps} from '../../components/Toast/Toast.type'; +import Toast from '../../components/Toast/Toast'; + +export const ToastContext = createContext(null); + +const DEFAULT_TIME = 3000; + +interface ToastContextProps { + showToast: (args: ShowToast) => void; +} + +type ShowToast = ToastProps & { + showingTime?: number; + isAlwaysOn?: boolean; +}; + +export const ToastProvider = ({children}: React.PropsWithChildren) => { + const [currentToast, setCurrentToast] = useState(null); + + const showToast = ({showingTime = DEFAULT_TIME, isAlwaysOn = false, ...toastProps}: ShowToast) => { + setCurrentToast({showingTime, isAlwaysOn, ...toastProps}); + }; + + const closeToast = () => { + setCurrentToast(null); + }; + + useEffect(() => { + if (currentToast && !currentToast.isAlwaysOn) { + const timer = setTimeout(() => setCurrentToast(null), currentToast.showingTime); + + return () => clearTimeout(timer); + } + + return; + }, [currentToast]); + + return ( + + {currentToast && } + {children} + + ); +}; diff --git a/client/src/hooks/useToast/useToast.test.tsx b/client/src/hooks/useToast/useToast.test.tsx new file mode 100644 index 000000000..f790ba98e --- /dev/null +++ b/client/src/hooks/useToast/useToast.test.tsx @@ -0,0 +1,80 @@ +import {render, renderHook, screen, waitFor} from '@testing-library/react'; +import {act} from 'react'; +import {HDesignProvider} from 'haengdong-design'; + +import {ToastProvider} from './ToastProvider'; // ์œ„ ์ฝ”๋“œ์— ํ•ด๋‹นํ•˜๋Š” ToastProvider ๊ฒฝ๋กœ +import {useToast} from './useToast'; + +const TOAST_CONFIG = { + message: 'Test Toast Message', +}; + +// ํ…Œ์ŠคํŠธ์šฉ ํ—ฌํผ ์ปดํฌ๋„ŒํŠธ +const TestComponent = () => { + const {showToast} = useToast(); + + const handleClick = () => { + showToast(TOAST_CONFIG); + }; + + return ; +}; + +const setup = () => + render( + + + + + , + ); + +describe('ToastProvider', () => { + it('ํ† ์ŠคํŠธ๋ฅผ ๋„์šฐ๊ณ  ์ž๋™์œผ๋กœ ์‚ฌ๋ผ์ง€๊ฒŒ ํ•œ๋‹ค', async () => { + setup(); + + // ํ† ์ŠคํŠธ๋ฅผ ๋„์šฐ๊ธฐ ์œ„ํ•ด ๋ฒ„ํŠผ ํด๋ฆญ + act(() => { + screen.getByText('Show Toast').click(); + }); + + // ํ† ์ŠคํŠธ ๋ฉ”์‹œ์ง€๊ฐ€ ๋‚˜ํƒ€๋‚˜๋Š”์ง€ ํ™•์ธ + expect(screen.getByText(TOAST_CONFIG.message)).toBeInTheDocument(); + + // 1์ดˆ ํ›„์— ํ† ์ŠคํŠธ ๋ฉ”์‹œ์ง€๊ฐ€ ์‚ฌ๋ผ์ง€๋Š”์ง€ ํ™•์ธ + await waitFor( + () => { + expect(screen.queryByText(TOAST_CONFIG.message)).not.toBeInTheDocument(); + }, + {timeout: 3100}, + ); // ํƒ€์ž„์•„์›ƒ์„ 3100ms๋กœ ์„ค์ •ํ•˜์—ฌ ์ •ํ™•ํžˆ 3์ดˆ ํ›„ ํ™•์ธ + }); + + it('ํ† ์ŠคํŠธ ๋‹ซ๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ์‚ฌ๋ผ์ง„๋‹ค', async () => { + setup(); + + // ํ† ์ŠคํŠธ๋ฅผ ๋„์šฐ๊ธฐ ์œ„ํ•ด ๋ฒ„ํŠผ ํด๋ฆญ + act(() => { + screen.getByText('Show Toast').click(); + }); + + // ํ† ์ŠคํŠธ ๋ฉ”์‹œ์ง€๊ฐ€ ๋‚˜ํƒ€๋‚˜๋Š”์ง€ ํ™•์ธ + expect(screen.getByText(TOAST_CONFIG.message)).toBeInTheDocument(); + + // ํ† ์ŠคํŠธ์˜ ๋‹ซ๊ธฐ ๋ฒ„ํŠผ์„ ํด๋ฆญ + act(() => { + document.getElementById('toast')?.click(); + }); + + // ๋‹ซ๊ธฐ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•œ ํ›„ ํ† ์ŠคํŠธ๊ฐ€ ์‚ฌ๋ผ์ง€๋Š”์ง€ ํ™•์ธ + await waitFor(() => { + expect(screen.queryByText(TOAST_CONFIG.message)).not.toBeInTheDocument(); + }); + }); + + it('Provider์—†์ด useToast ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ์—๋Ÿฌ๋ฅผ ๋˜์ง„๋‹ค.', () => { + expect(() => { + const _ = renderHook(() => useToast()); + }).toThrow('useToast๋Š” ToastProvider ๋‚ด์—์„œ ์‚ฌ์šฉ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); + }); +}); diff --git a/client/src/hooks/useToast/useToast.tsx b/client/src/hooks/useToast/useToast.tsx new file mode 100644 index 000000000..189847405 --- /dev/null +++ b/client/src/hooks/useToast/useToast.tsx @@ -0,0 +1,13 @@ +import {useContext} from 'react'; + +import {ToastContext} from './ToastProvider'; + +export const useToast = () => { + const context = useContext(ToastContext); + + if (!context) { + throw new Error('useToast๋Š” ToastProvider ๋‚ด์—์„œ ์‚ฌ์šฉ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.'); + } + + return context; +}; diff --git a/client/src/index.tsx b/client/src/index.tsx new file mode 100644 index 000000000..17f98655f --- /dev/null +++ b/client/src/index.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import {RouterProvider} from 'react-router-dom'; +import * as Sentry from '@sentry/react'; + +import router from './router'; + +// async function enableMocking() { +// const {worker} = await import('./mocks/browser'); +// return worker.start(); +// } + +Sentry.init({ + dsn: 'https://81685591a3234c689be8c48959b04c88@o4507739935997952.ingest.us.sentry.io/4507739943272448', + integrations: [Sentry.browserTracingIntegration(), Sentry.replayIntegration()], + // Performance Monitoring + tracesSampleRate: 1.0, // Capture 100% of the transactions + // Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled + tracePropagationTargets: ['localhost', /^https:\/\/api\.haengdong\.pro/], + // Session Replay + replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production. + replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur. +}); + +// MSW ๋ชจํ‚น์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์•„๋ž˜ ์ฃผ์„์„ ํ•ด์ œํ•˜๊ณ  saveํ•ด์ฃผ์„ธ์š”. +// enableMocking().then(() => { +ReactDOM.createRoot(document.getElementById('root')!).render( + + + , +); +// }); diff --git a/client/src/mocks/browser.ts b/client/src/mocks/browser.ts new file mode 100644 index 000000000..dd8d73b6c --- /dev/null +++ b/client/src/mocks/browser.ts @@ -0,0 +1,5 @@ +import {setupWorker} from 'msw/browser'; + +import {handlers} from './handlers'; + +export const worker = setupWorker(...handlers); diff --git a/client/src/mocks/handlers.ts b/client/src/mocks/handlers.ts new file mode 100644 index 000000000..4189b2d66 --- /dev/null +++ b/client/src/mocks/handlers.ts @@ -0,0 +1,15 @@ +import {authHandler} from './handlers/authHandlers'; +import {eventHandler} from './handlers/eventHandlers'; +import {reportHandlers} from './handlers/reportHandlers'; +import {stepListHandler} from './handlers/stepListHandler'; +import {testHandler} from './handlers/testHandlers'; +import {memberReportInActionHandler} from './handlers/memberReportInActionHandlers'; + +export const handlers = [ + ...authHandler, + ...eventHandler, + ...testHandler, + ...stepListHandler, + ...reportHandlers, + ...memberReportInActionHandler, +]; diff --git a/client/src/mocks/handlers/authHandlers.ts b/client/src/mocks/handlers/authHandlers.ts new file mode 100644 index 000000000..31532eea7 --- /dev/null +++ b/client/src/mocks/handlers/authHandlers.ts @@ -0,0 +1,104 @@ +import {HttpResponse, http} from 'msw'; + +import {TEMP_PREFIX} from '@apis/tempPrefix'; + +import {PASSWORD_LENGTH} from '@constants/password'; + +import { + EXPIRED_TOKEN_FOR_TEST, + FORBIDDEN_TOKEN_FOR_TEST, + VALID_PASSWORD_FOR_TEST, + VALID_TOKEN_FOR_TEST, +} from '@mocks/validValueForTest'; + +type PostLoginParams = { + eventId: string; +}; + +type PostLoginRequestBody = { + password: string; +}; + +export const authHandler = [ + http.post(`${TEMP_PREFIX}/:eventId/auth`, ({cookies}) => { + const token = cookies['eventToken']; + + if (token === VALID_TOKEN_FOR_TEST) { + return new HttpResponse(null, { + status: 200, + }); + } else if (token === EXPIRED_TOKEN_FOR_TEST) { + return HttpResponse.json( + { + errorCode: 'TOKEN_EXPIRED', + message: '๋งŒ๋ฃŒ๋œ ํ† ํฐ์ž…๋‹ˆ๋‹ค.', + }, + {status: 401}, + ); + } else if (token === FORBIDDEN_TOKEN_FOR_TEST) { + return HttpResponse.json( + { + errorCode: 'FORBIDDEN', + message: '์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค.', + }, + {status: 401}, + ); + } else if (token === undefined) { + return HttpResponse.json( + { + errorCode: 'TOKEN_NOT_FOUND', + message: 'ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.', + }, + {status: 401}, + ); + } else { + return HttpResponse.json( + { + errorCode: 'TOKEN_INVALID', + message: '์œ ํšจํ•˜์ง€ ์•Š์€ ํ† ํฐ์ž…๋‹ˆ๋‹ค.', + }, + {status: 401}, + ); + } + }), + + // TODO: (@weadie) any๋ฅผ ์‚ฌ์šฉํ•œ ์ด์œ ๋Š”.. any๊ฐ€ ์žˆ๋Š” ์œ„์น˜๊ฐ€ ์ด handlerํ•จ์ˆ˜์˜ responseBodyํƒ€์ž…์ธ๋ฐ, ์•„๋ž˜์ฒ˜๋Ÿผ returnํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ์˜ˆ์‹œ๊ฐ€ ๊ณต๋ฌธ์— ์—†์Šต๋‹ˆ๋‹ค. ํ•จ์ˆ˜๋ฅผ ๊นŒ๋ฉด ๋˜๊ฒ ์ง€๋งŒ ์‹œ๊ฐ„์ด ์•„๊น๊ณ  ์•Œ์•„๋‚ธ๋‹ค๊ณ  ํ•ด์„œ ์ด responseBody ํƒ€์ž…์€ ์‚ฌ์‹ค ์ค‘์š”ํ•œ๊ฒŒ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— any๋กœ ๋Œ€์ฒดํ•˜์˜€์Šต๋‹ˆ๋‹ค. + http.post( + `${TEMP_PREFIX}/:eventId/login`, + async ({request}) => { + const {password} = await request.json(); + + if (password === String(VALID_PASSWORD_FOR_TEST)) { + return new HttpResponse(null, { + headers: { + 'Set-Cookie': 'eventToken=abc-123', + }, + }); + } else if (password.length < PASSWORD_LENGTH) { + return HttpResponse.json( + { + errorCode: 'EVENT_PASSWORD_FORMAT_INVALID', + message: `๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ${PASSWORD_LENGTH}์ž๋ฆฌ ์ˆซ์ž๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.`, + }, + {status: 401}, + ); + } else if (password === undefined) { + return HttpResponse.json( + { + errorCode: 'REQUEST_EMPTY', + message: '๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.', + }, + {status: 401}, + ); + } else { + return HttpResponse.json( + { + errorCode: 'PASSWORD_INVALID', + message: '๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.', + }, + {status: 401}, + ); + } + }, + ), +]; diff --git a/client/src/mocks/handlers/eventHandlers.ts b/client/src/mocks/handlers/eventHandlers.ts new file mode 100644 index 000000000..351993e16 --- /dev/null +++ b/client/src/mocks/handlers/eventHandlers.ts @@ -0,0 +1,55 @@ +import {HttpResponse, http} from 'msw'; + +import {RequestPostNewEvent, ResponsePostNewEvent} from '@apis/request/event'; + +import {TEMP_PREFIX} from '@apis/tempPrefix'; + +import {PASSWORD_LENGTH} from '@constants/password'; + +import {VALID_EVENT_NAME_LENGTH_IN_SERVER} from '@mocks/serverConstants'; + +type ErrorResponseBody = { + errorCode: string; + message: string; +}; + +export const eventHandler = [ + http.post( + `${TEMP_PREFIX}`, + async ({request}) => { + const {eventName, password} = await request.json(); + + if (String(password).length < PASSWORD_LENGTH) { + return HttpResponse.json( + { + errorCode: 'EVENT_PASSWORD_FORMAT_INVALID', + message: '๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” 4์ž๋ฆฌ ์ˆซ์ž๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.', + }, + {status: 401}, + ); + } else if ( + eventName.length < VALID_EVENT_NAME_LENGTH_IN_SERVER.min || + eventName.length > VALID_EVENT_NAME_LENGTH_IN_SERVER.max + ) { + return HttpResponse.json( + { + errorCode: 'EVENT_NAME_LENGTH_INVALID', + message: `ํ–‰์‚ฌ ์ด๋ฆ„์€ 2์ž ์ด์ƒ 30์ž ์ดํ•˜๋งŒ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ž…๋ ฅํ•œ ์ด๋ฆ„ ๊ธธ์ด : ${eventName.length}`, + }, + {status: 401}, + ); + } else { + return HttpResponse.json( + { + eventId: 'eventId', + }, + { + headers: { + 'Set-Cookie': 'eventToken=abc-123', + }, + }, + ); + } + }, + ), +]; diff --git a/client/src/mocks/handlers/memberReportInActionHandlers.ts b/client/src/mocks/handlers/memberReportInActionHandlers.ts new file mode 100644 index 000000000..45de357f1 --- /dev/null +++ b/client/src/mocks/handlers/memberReportInActionHandlers.ts @@ -0,0 +1,49 @@ +import {http, HttpResponse} from 'msw'; + +import {MemberReport} from 'types/serviceType'; + +import {TEMP_PREFIX} from '@apis/tempPrefix'; + +import memberReportInActionJson from '../memberReportListInAction.json'; + +let memberReportInActionMockData = memberReportInActionJson as MemberReport[]; + +type MemberReportListRequestParams = { + eventId: string; + actionId: string; +}; +type MemberReportListBody = {members: MemberReport[]}; + +export const memberReportInActionHandler = [ + http.get< + MemberReportListRequestParams, + MemberReportListBody, + any, + `${typeof TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed` + >(`${TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed`, ({params}) => { + const {actionId} = params; + + if (Number(actionId) === 123) { + return HttpResponse.json({ + members: memberReportInActionMockData, + }); + } + + return HttpResponse.json({ + members: memberReportInActionMockData.slice(0, 2), + }); + }), + + http.put( + `${TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed`, + async ({request}) => { + const {members} = await request.json(); + + memberReportInActionMockData = members; + + return HttpResponse.json({ + status: 200, + }); + }, + ), +]; diff --git a/client/src/mocks/handlers/reportHandlers.ts b/client/src/mocks/handlers/reportHandlers.ts new file mode 100644 index 000000000..6b256d7d3 --- /dev/null +++ b/client/src/mocks/handlers/reportHandlers.ts @@ -0,0 +1,13 @@ +import {HttpResponse, http} from 'msw'; + +import {TEMP_PREFIX} from '@apis/tempPrefix'; + +import reportListJson from '../reportList.json'; + +export const reportHandlers = [ + http.get(`${TEMP_PREFIX}/:eventId/actions/reports`, () => { + return HttpResponse.json({ + reports: reportListJson, + }); + }), +]; diff --git a/client/src/mocks/handlers/stepListHandler.ts b/client/src/mocks/handlers/stepListHandler.ts new file mode 100644 index 000000000..d79b7b0b4 --- /dev/null +++ b/client/src/mocks/handlers/stepListHandler.ts @@ -0,0 +1,113 @@ +import {HttpResponse, http} from 'msw'; + +import {Bill, MemberType, StepList} from 'types/serviceType'; + +import {TEMP_PREFIX} from '@apis/tempPrefix'; + +import stepListJson from '../stepList.json'; + +type StepListResponseBody = { + step: StepList; +}; + +type PostMemberListRequestBody = { + members: string[]; + status: MemberType; +}; + +type PostBillListRequestBody = { + actions: Bill[]; +}; + +let stepListMockData = stepListJson; + +export const stepListHandler = [ + http.get( + `${TEMP_PREFIX}/:eventId/actions`, + () => { + return HttpResponse.json({ + steps: stepListMockData, + }); + }, + ), + + http.get(`${TEMP_PREFIX}/:eventId/members`, () => { + return HttpResponse.json({ + memberNames: stepListMockData + .filter(({type}) => type !== 'BILL') + .map(({actions}) => actions.map(({name}) => name)) + .flat(), + }); + }), + + http.delete<{actionId: string}>(`${TEMP_PREFIX}/:eventId/member-actions/:actionId`, ({params}) => { + const {actionId} = params; + + if (parseInt(actionId) === 999) { + return HttpResponse.json( + { + errorCode: 'MEMBER_ACTION_STATUS_INVALID', + message: 'actionId๋Š” 999์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.(๊ณ ์˜๋กœ ๋งŒ๋“  ์—๋Ÿฌ์ž„)', + }, + {status: 401}, + ); + } else { + return HttpResponse.json({ + status: 200, + }); + } + }), + + http.post( + `${TEMP_PREFIX}/:eventId/member-actions`, + async ({request}) => { + const {members, status} = await request.json(); + stepListMockData = [ + ...stepListJson, + { + type: status, + stepName: '์˜์ฐจ์˜์ฐจ', + members: status === 'IN' ? members : [], + actions: members.map(name => ({ + actionId: 999, + name, + price: 0, + sequence: 999, + isFixed: false, + })), + }, + ]; + + return HttpResponse.json({ + status: 200, + }); + }, + ), + + http.post( + `${TEMP_PREFIX}/:eventId/bill-actions`, + async ({request}) => { + const {actions} = await request.json(); + + stepListMockData = [ + ...stepListJson, + { + type: 'BILL', + stepName: '๋ฐฅ์Šค์นด์ด', + members: [], + actions: actions.map(({title, price}) => ({ + actionId: 999, + name: title, + price, + sequence: 999, + isFixed: false, + })), + }, + ]; + + return HttpResponse.json({ + status: 200, + }); + }, + ), +]; diff --git a/client/src/mocks/handlers/testHandlers.ts b/client/src/mocks/handlers/testHandlers.ts new file mode 100644 index 000000000..fda96a1f0 --- /dev/null +++ b/client/src/mocks/handlers/testHandlers.ts @@ -0,0 +1,23 @@ +import {HttpResponse, http} from 'msw'; + +export const testHandler = [ + http.post(`/throw-handle-error`, () => { + return HttpResponse.json( + { + errorCode: 'TOKEN_NOT_FOUND', + message: 'ํ•ธ๋“ค๋ง๋˜๋Š” ํ…Œ์ŠคํŠธ ์—๋Ÿฌ์ž…๋‹ˆ๋‹ค.', + }, + {status: 400}, + ); + }), + + http.post(`/throw-unhandle-error`, () => { + return HttpResponse.json( + { + errorCode: 'strange error', + message: 'ํ•ธ๋“ค๋ง์ด ์•ˆ๋˜๋Š” ํ…Œ์ŠคํŠธ ์—๋Ÿฌ์ž…๋‹ˆ๋‹ค.', + }, + {status: 500}, + ); + }), +]; diff --git a/client/src/mocks/invalidMemberStepList.json b/client/src/mocks/invalidMemberStepList.json new file mode 100644 index 000000000..33ca77e4c --- /dev/null +++ b/client/src/mocks/invalidMemberStepList.json @@ -0,0 +1,100 @@ +[ + { + "type": "IN", + "stepName": null, + "members": [], + "actions": [ + { + "actionId": 999, + "name": "๋ง์ตธ", + "price": null, + "sequence": 1, + "isFixed": false + }, + { + "actionId": 2, + "name": "๋ฐฑํ˜ธ", + "price": null, + "sequence": 2, + "isFixed": false + } + ] + }, + { + "type": "BILL", + "stepName": "1์ฐจ", + "members": ["๋ง์ตธ", "๋ฐฑํ˜ธ"], + "actions": [ + { + "actionId": 3, + "name": "๊ฐ์žํƒ•", + "price": 10000, + "sequence": 3, + "isFixed": false + }, + { + "actionId": 4, + "name": "์ธ์ƒ๋„ค์ปท", + "price": 10000, + "sequence": 4, + "isFixed": false + } + ] + }, + { + "type": "IN", + "stepName": null, + "members": [], + "actions": [ + { + "actionId": 5, + "name": "์†Œํ•˜", + "price": null, + "sequence": 5, + "isFixed": false + }, + { + "actionId": 6, + "name": "์›จ๋””", + "price": null, + "sequence": 6, + "isFixed": false + } + ] + }, + { + "type": "BILL", + "stepName": "2์ฐจ", + "members": ["์†Œํ•˜", "์›จ๋””"], + "actions": [ + { + "actionId": 9, + "name": "๋…ธ๋ž˜๋ฐฉ", + "price": 20000, + "sequence": 10, + "isFixed": false + } + ] + }, + { + "type": "OUT", + "stepName": null, + "members": [], + "actions": [ + { + "actionId": 7, + "name": "๋ง์ตธ", + "price": null, + "sequence": 7, + "isFixed": false + }, + { + "actionId": 8, + "name": "๋ฐฑํ˜ธ", + "price": null, + "sequence": 8, + "isFixed": false + } + ] + } +] diff --git a/client/src/mocks/memberActionStepList.json b/client/src/mocks/memberActionStepList.json new file mode 100644 index 000000000..734db4a75 --- /dev/null +++ b/client/src/mocks/memberActionStepList.json @@ -0,0 +1,23 @@ +[ + { + "type": "IN", + "stepName": null, + "members": [], + "actions": [ + { + "actionId": 1, + "name": "๋ง์ตธ", + "price": null, + "sequence": 1, + "isFixed": false + }, + { + "actionId": 2, + "name": "๋ฐฑํ˜ธ", + "price": null, + "sequence": 2, + "isFixed": false + } + ] + } +] diff --git a/client/src/mocks/memberReportListInAction.json b/client/src/mocks/memberReportListInAction.json new file mode 100644 index 000000000..2e24670cb --- /dev/null +++ b/client/src/mocks/memberReportListInAction.json @@ -0,0 +1,6 @@ +[ + {"name": "๋ง์ตธ", "price": 25000, "isFixed": false}, + {"name": "์ด์ƒ", "price": 25000, "isFixed": false}, + {"name": "์†Œํ•˜", "price": 25000, "isFixed": false}, + {"name": "์ฟ ํ‚ค", "price": 25000, "isFixed": false} +] diff --git a/client/src/mocks/memberReportSearchList.json b/client/src/mocks/memberReportSearchList.json new file mode 100644 index 000000000..dfcb684b1 --- /dev/null +++ b/client/src/mocks/memberReportSearchList.json @@ -0,0 +1,10 @@ +[ + {"name": "๋ง์ตธ", "price": 1033200}, + {"name": "์ด์ƒ", "price": 10100}, + {"name": "์†Œํ•˜", "price": 10000}, + {"name": "์ฟ ํ‚ค", "price": 100012}, + {"name": "ํ† ๋‹ค๋ฆฌ", "price": 1001230}, + {"name": "๊ฐ์ž", "price": 1012300}, + {"name": "๋ฐฑํ˜ธ", "price": 10300}, + {"name": "์›จ๋””", "price": 1000} +] diff --git a/client/src/mocks/reportList.json b/client/src/mocks/reportList.json new file mode 100644 index 000000000..a663eb9fd --- /dev/null +++ b/client/src/mocks/reportList.json @@ -0,0 +1,18 @@ +[ + { + "name": "์†Œํ•˜", + "price": 40000 + }, + { + "name": "๊ฐ์ž", + "price": 20000 + }, + { + "name": "์ฟ ํ‚ค", + "price": 40000 + }, + { + "name": "ํ† ๋‹ค๋ฆฌ", + "price": 0 + } +] diff --git a/client/src/mocks/server.ts b/client/src/mocks/server.ts new file mode 100644 index 000000000..157a298e0 --- /dev/null +++ b/client/src/mocks/server.ts @@ -0,0 +1,5 @@ +import {setupServer} from 'msw/node'; + +import {handlers} from './handlers'; + +export const server = setupServer(...handlers); diff --git a/client/src/mocks/serverConstants.ts b/client/src/mocks/serverConstants.ts new file mode 100644 index 000000000..1063a2f75 --- /dev/null +++ b/client/src/mocks/serverConstants.ts @@ -0,0 +1,4 @@ +export const VALID_EVENT_NAME_LENGTH_IN_SERVER = { + min: 2, + max: 30, +}; diff --git a/client/src/mocks/stepList.json b/client/src/mocks/stepList.json new file mode 100644 index 000000000..355692d58 --- /dev/null +++ b/client/src/mocks/stepList.json @@ -0,0 +1,100 @@ +[ + { + "type": "IN", + "stepName": null, + "members": [], + "actions": [ + { + "actionId": 1, + "name": "๋ง์ตธ", + "price": null, + "sequence": 1, + "isFixed": false + }, + { + "actionId": 2, + "name": "๋ฐฑํ˜ธ", + "price": null, + "sequence": 2, + "isFixed": false + } + ] + }, + { + "type": "BILL", + "stepName": "1์ฐจ", + "members": ["๋ง์ตธ", "๋ฐฑํ˜ธ"], + "actions": [ + { + "actionId": 3, + "name": "๊ฐ์žํƒ•", + "price": 10000, + "sequence": 3, + "isFixed": false + }, + { + "actionId": 4, + "name": "์ธ์ƒ๋„ค์ปท", + "price": 10000, + "sequence": 4, + "isFixed": false + } + ] + }, + { + "type": "IN", + "stepName": null, + "members": [], + "actions": [ + { + "actionId": 5, + "name": "์†Œํ•˜", + "price": null, + "sequence": 5, + "isFixed": false + }, + { + "actionId": 6, + "name": "์›จ๋””", + "price": null, + "sequence": 6, + "isFixed": false + } + ] + }, + { + "type": "BILL", + "stepName": "2์ฐจ", + "members": ["์†Œํ•˜", "์›จ๋””"], + "actions": [ + { + "actionId": 9, + "name": "๋…ธ๋ž˜๋ฐฉ", + "price": 20000, + "sequence": 10, + "isFixed": false + } + ] + }, + { + "type": "OUT", + "stepName": null, + "members": [], + "actions": [ + { + "actionId": 7, + "name": "๋ง์ตธ", + "price": null, + "sequence": 7, + "isFixed": false + }, + { + "actionId": 8, + "name": "๋ฐฑํ˜ธ", + "price": null, + "sequence": 8, + "isFixed": false + } + ] + } +] diff --git a/client/src/mocks/svg.ts b/client/src/mocks/svg.ts new file mode 100644 index 000000000..ffe2050a0 --- /dev/null +++ b/client/src/mocks/svg.ts @@ -0,0 +1,2 @@ +export default 'SvgrURL'; +export const ReactComponent = 'div'; diff --git a/client/src/mocks/validValueForTest.ts b/client/src/mocks/validValueForTest.ts new file mode 100644 index 000000000..31f587134 --- /dev/null +++ b/client/src/mocks/validValueForTest.ts @@ -0,0 +1,4 @@ +export const VALID_PASSWORD_FOR_TEST = 1111; +export const VALID_TOKEN_FOR_TEST = 'valid-token'; +export const FORBIDDEN_TOKEN_FOR_TEST = 'forbidden-token'; +export const EXPIRED_TOKEN_FOR_TEST = 'expired-token'; diff --git a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx new file mode 100644 index 000000000..066165d6a --- /dev/null +++ b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx @@ -0,0 +1,29 @@ +import {useLocation, useNavigate} from 'react-router-dom'; +import {FixedButton, MainLayout, Title, TopNav} from 'haengdong-design'; + +import {RunningDog} from '@components/Common/Logo'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +const CompleteCreateEventPage = () => { + const navigate = useNavigate(); + const location = useLocation(); + + const params = new URLSearchParams(location.search); + const eventId = params.get('eventId'); + + return ( + + + + <RunningDog /> + <FixedButton onClick={() => navigate(`${ROUTER_URLS.event}/${eventId}/admin`)}>๊ด€๋ฆฌ ํŽ˜์ด์ง€๋กœ ์ด๋™</FixedButton> + </MainLayout> + ); +}; + +export default CompleteCreateEventPage; diff --git a/client/src/pages/CreateEventPage/SetEventNamePage.tsx b/client/src/pages/CreateEventPage/SetEventNamePage.tsx new file mode 100644 index 000000000..ad68327d2 --- /dev/null +++ b/client/src/pages/CreateEventPage/SetEventNamePage.tsx @@ -0,0 +1,42 @@ +import {useNavigate} from 'react-router-dom'; +import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from 'haengdong-design'; +import {css} from '@emotion/react'; + +import useSetEventNamePage from '@hooks/useSetEventNamePage'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +const SetEventNamePage = () => { + const navigate = useNavigate(); + const {eventName, errorMessage, canSubmit, handleEventNameChange} = useSetEventNamePage(); + + const submitEventName = (event: React.FormEvent<HTMLFormElement>) => { + event.preventDefault(); + + navigate(ROUTER_URLS.eventCreatePassword, {state: {eventName}}); + }; + + return ( + <MainLayout backgroundColor="white"> + <TopNav> + <Back /> + </TopNav> + <Title title="ํ–‰์‚ฌ ์ด๋ฆ„ ์ž…๋ ฅ" description="์‹œ์ž‘ํ•  ํ–‰์‚ฌ ์ด๋ฆ„์„ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”." /> + <form onSubmit={submitEventName} css={css({padding: '0 1rem'})}> + <LabelInput + labelText="ํ–‰์‚ฌ ์ด๋ฆ„" + errorText={errorMessage ?? ''} + value={eventName} + type="text" + placeholder="ํ–‰์‚ฌ ์ด๋ฆ„" + onChange={handleEventNameChange} + isError={!!errorMessage} + autoFocus + ></LabelInput> + <FixedButton disabled={!canSubmit}>๋‹ค์Œ</FixedButton> + </form> + </MainLayout> + ); +}; + +export default SetEventNamePage; diff --git a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx new file mode 100644 index 000000000..14fcdd75b --- /dev/null +++ b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx @@ -0,0 +1,41 @@ +import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from 'haengdong-design'; + +import useSetEventPasswordPage from '@hooks/useSetEventPasswordPage'; + +import RULE from '@constants/rule'; +import {PASSWORD_LENGTH} from '@constants/password'; + +const SetEventPasswordPage = () => { + const {submitPassword, errorMessage, password, handleChange, canSubmit, isPostEventPending} = + useSetEventPasswordPage(); + + return ( + <MainLayout backgroundColor="white"> + <TopNav> + <Back /> + </TopNav> + <Title + title="ํ–‰์‚ฌ ๋น„๋ฐ€๋ฒˆํ˜ธ ์„ค์ •" + description={`ํ–‰์‚ฌ ๊ด€๋ฆฌ์— ํ•„์š”ํ•œ ${PASSWORD_LENGTH} ์ž๋ฆฌ์˜ ์ˆซ์ž ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.`} + /> + <form onSubmit={submitPassword} style={{padding: '0 1rem'}}> + <LabelInput + labelText="๋น„๋ฐ€๋ฒˆํ˜ธ" + errorText={errorMessage} + value={password} + type="text" + maxLength={RULE.maxEventPasswordLength} + placeholder="๋น„๋ฐ€๋ฒˆํ˜ธ" + onChange={handleChange} + isError={!!errorMessage} + autoFocus + /> + <FixedButton variants={isPostEventPending ? 'loading' : 'primary'} disabled={!canSubmit}> + ํ–‰๋™ ๊ฐœ์‹œ! + </FixedButton> + </form> + </MainLayout> + ); +}; + +export default SetEventPasswordPage; diff --git a/client/src/pages/CreateEventPage/index.ts b/client/src/pages/CreateEventPage/index.ts new file mode 100644 index 000000000..6d3d6c808 --- /dev/null +++ b/client/src/pages/CreateEventPage/index.ts @@ -0,0 +1,3 @@ +export {default as SetEventNamePage} from './SetEventNamePage'; +export {default as SetEventPasswordPage} from './SetEventPasswordPage'; +export {default as CompleteCreateEventPage} from './CompleteCreateEventPage'; diff --git a/client/src/pages/ErrorPage/ErrorPage.tsx b/client/src/pages/ErrorPage/ErrorPage.tsx new file mode 100644 index 000000000..31ef8c81f --- /dev/null +++ b/client/src/pages/ErrorPage/ErrorPage.tsx @@ -0,0 +1,14 @@ +import {MainLayout, Title} from 'haengdong-design'; + +const ErrorPage = () => { + return ( + <MainLayout> + <Title + title="์•Œ ์ˆ˜ ์—†๋Š” ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค." + description="์˜ค๋ฅ˜๊ฐ€ ๋‚œ ์ƒํ™ฉ์— ๋Œ€ํ•ด haengdongdj@gmail.com ๋กœ ์—ฐ๋ฝ์ฃผ์‹œ๋ฉด ์†Œ์ •์˜ ์ƒํ’ˆ์„ ๋“œ๋ฆฝ๋‹ˆ๋‹ค." + /> + </MainLayout> + ); +}; + +export default ErrorPage; diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.style.ts b/client/src/pages/EventPage/AdminPage/AdminPage.style.ts new file mode 100644 index 000000000..cf6bb0042 --- /dev/null +++ b/client/src/pages/EventPage/AdminPage/AdminPage.style.ts @@ -0,0 +1,23 @@ +import {css} from '@emotion/react'; + +export const receiptStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + gap: '1rem', + paddingBottom: '2rem', + }); + +export const titleAndListButtonContainerStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + }); + +export const buttonGroupStyle = () => + css({ + display: 'flex', + width: '100%', + padding: '0 0.5rem', + gap: '0.5rem', + }); diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx new file mode 100644 index 000000000..79deeac7a --- /dev/null +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -0,0 +1,90 @@ +import {useEffect, useState} from 'react'; +import {Title, FixedButton, ListButton, Button} from 'haengdong-design'; +import {useOutletContext} from 'react-router-dom'; + +import StepList from '@components/StepList/StepList'; +import {ModalBasedOnMemberCount, SetAllMemberListModal} from '@components/Modal/index'; +import useRequestGetAllMemberList from '@hooks/queries/useRequestGetAllMemberList'; +import useRequestPostAuthenticate from '@hooks/queries/useRequestPostAuthentication'; + +import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; + +import {EventPageContextProps} from '../EventPageLayout'; + +import {receiptStyle, titleAndListButtonContainerStyle, buttonGroupStyle} from './AdminPage.style'; + +const AdminPage = () => { + const [isOpenFixedButtonBottomSheet, setIsOpenFixedButtonBottomSheet] = useState(false); + const [isOpenAllMemberListButton, setIsOpenAllMemberListButton] = useState(false); + const [isAddEditableItem, setIsAddEditableItem] = useState(false); + + const {eventName} = useOutletContext<EventPageContextProps>(); + const {data: allMemberListData} = useRequestGetAllMemberList(); + const allMemberList = allMemberListData?.memberNames ?? []; + + const {totalExpenseAmount} = useTotalExpenseAmountStore(); + + const {mutate: postAuthentication} = useRequestPostAuthenticate(); + + useEffect(() => { + postAuthentication(); + }, [postAuthentication]); + + const handleOpenAllMemberListButton = () => { + setIsOpenFixedButtonBottomSheet(prev => !prev); + setIsOpenAllMemberListButton(prev => !prev); + }; + + const getTitleDescriptionByInitialMemberSetting = () => { + return allMemberList.length > 0 + ? `์ง€์ถœ ๋‚ด์—ญ ๋ฐ ์ธ์› ๋ณ€๋™์„ ์ถ”๊ฐ€ํ•ด ์ฃผ์„ธ์š”. + ์ธ์› ๋ณ€๋™์„ ๊ธฐ์ค€์œผ๋กœ ๋ช‡ ์ฐจ์ธ์ง€ ๋‚˜๋‰˜์–ด์ ธ์š”.` + : 'โ€œ์‹œ์ž‘ ์ธ์› ์ถ”๊ฐ€โ€ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ํ–‰์‚ฌ์˜ ์‹œ์ž‘๋ถ€ํ„ฐ ์ฐธ์—ฌํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์˜ ์ด๋ฆ„์„ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.'; + }; + + return ( + <> + <div css={titleAndListButtonContainerStyle}> + <Title title={eventName} description={getTitleDescriptionByInitialMemberSetting()} price={totalExpenseAmount} /> + {allMemberList.length !== 0 && ( + <ListButton + prefix="์ „์ฒด ์ฐธ์—ฌ์ž" + suffix={`${allMemberList.length}๋ช…`} + onClick={handleOpenAllMemberListButton} + /> + )} + </div> + <section css={receiptStyle}> + <StepList isAddEditableItem={isAddEditableItem} setIsAddEditableItem={setIsAddEditableItem} /> + {allMemberList.length === 0 ? ( + <FixedButton children={'์‹œ์ž‘์ธ์› ์ถ”๊ฐ€ํ•˜๊ธฐ'} onClick={() => setIsOpenFixedButtonBottomSheet(prev => !prev)} /> + ) : ( + <div css={buttonGroupStyle}> + <Button + size="medium" + variants="tertiary" + style={{width: '100%'}} + onClick={() => setIsOpenFixedButtonBottomSheet(prev => !prev)} + > + ์ธ์› ๋ณ€๋™ ์ถ”๊ฐ€ + </Button> + <Button size="medium" onClick={() => setIsAddEditableItem(true)} style={{width: '100%'}}> + ์ง€์ถœ ๋‚ด์—ญ ์ถ”๊ฐ€ + </Button> + </div> + )} + {isOpenFixedButtonBottomSheet && ( + <ModalBasedOnMemberCount + allMemberList={allMemberList} + setIsOpenBottomSheet={setIsOpenFixedButtonBottomSheet} + isOpenBottomSheet={isOpenFixedButtonBottomSheet} + isOpenAllMemberListButton={isOpenAllMemberListButton} + setIsOpenAllMemberListButton={setIsOpenAllMemberListButton} + /> + )} + </section> + </> + ); +}; + +export default AdminPage; diff --git a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx new file mode 100644 index 000000000..741dca3eb --- /dev/null +++ b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx @@ -0,0 +1,35 @@ +import {FixedButton, LabelInput, Title} from 'haengdong-design'; + +import useEventLogin from '@hooks/useEventLogin'; + +import RULE from '@constants/rule'; +import {PASSWORD_LENGTH} from '@constants/password'; + +const EventLoginPage = () => { + const {password, errorMessage, handleChange, canSubmit, submitPassword} = useEventLogin(); + + return ( + <> + <Title + title="ํ–‰์‚ฌ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ" + description={`๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด์„  ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ํ•„์š”ํ•ด์š”. ํ–‰์‚ฌ ์ƒ์„ฑ ์‹œ ์„ค์ •ํ•œ ${PASSWORD_LENGTH} ์ž๋ฆฌ์˜ ์ˆซ์ž ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.`} + /> + <form onSubmit={submitPassword} style={{padding: '0 1rem'}}> + <LabelInput + labelText="๋น„๋ฐ€๋ฒˆํ˜ธ" + errorText={errorMessage} + value={password} + type="secret" + maxLength={RULE.maxEventPasswordLength} + placeholder="๋น„๋ฐ€๋ฒˆํ˜ธ" + onChange={e => handleChange(e)} + isError={!!errorMessage} + autoFocus + ></LabelInput> + <FixedButton disabled={!canSubmit}>๊ด€๋ฆฌ ํŽ˜์ด์ง€๋กœ</FixedButton> + </form> + </> + ); +}; + +export default EventLoginPage; diff --git a/client/src/pages/EventPage/AdminPage/index.ts b/client/src/pages/EventPage/AdminPage/index.ts new file mode 100644 index 000000000..b80c0bb2f --- /dev/null +++ b/client/src/pages/EventPage/AdminPage/index.ts @@ -0,0 +1 @@ +export {default as AdminPage} from './AdminPage'; diff --git a/client/src/pages/EventPage/EventPageLayout.tsx b/client/src/pages/EventPage/EventPageLayout.tsx new file mode 100644 index 000000000..6f00c23f1 --- /dev/null +++ b/client/src/pages/EventPage/EventPageLayout.tsx @@ -0,0 +1,65 @@ +import {MainLayout, TopNav, Switch, Button} from 'haengdong-design'; +import {Outlet, useMatch} from 'react-router-dom'; +import CopyToClipboard from 'react-copy-to-clipboard'; + +import {useToast} from '@hooks/useToast/useToast'; +import useRequestGetEventName from '@hooks/queries/useRequestGetEventName'; + +import useNavSwitch from '@hooks/useNavSwitch'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; +import getEventPageUrlByEnvironment from '@utils/getEventPageUrlByEnvironment'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +export type EventPageContextProps = { + isAdmin: boolean; + eventName: string; +}; + +const EventPageLayout = () => { + const {nav, paths, onChange} = useNavSwitch(); + const {data} = useRequestGetEventName(); + const eventName = data?.eventName ?? ''; + const eventId = getEventIdByUrl(); + + const isAdmin = useMatch(ROUTER_URLS.eventManage) !== null; + const isLoginPage = useMatch(ROUTER_URLS.eventLogin) !== null; + + const outletContext: EventPageContextProps = { + isAdmin, + eventName, + }; + + const {showToast} = useToast(); + const url = getEventPageUrlByEnvironment(eventId, 'home'); + + return ( + <MainLayout backgroundColor="gray"> + <TopNav> + <Switch value={nav} values={paths} onChange={onChange} /> + {!isLoginPage && ( + <CopyToClipboard + text={`[ํ–‰๋™๋Œ€์žฅ]\n"${eventName}"์— ๋Œ€ํ•œ ์ •์‚ฐ์„ ์‹œ์ž‘ํ• ๊ฒŒ์š”:)\n์•„๋ž˜ ๋งํฌ์— ์ ‘์†ํ•ด์„œ ์ •์‚ฐ ๋‚ด์—ญ์„ ํ™•์ธํ•ด ์ฃผ์„ธ์š”!\n${url}`} + onCopy={() => + showToast({ + showingTime: 3000, + message: '๋งํฌ๊ฐ€ ๋ณต์‚ฌ๋˜์—ˆ์–ด์š” :) \n์ฐธ์—ฌ์ž๋“ค์—๊ฒŒ ๋งํฌ๋ฅผ ๊ณต์œ ํ•ด ์ฃผ์„ธ์š”!', + type: 'confirm', + position: 'bottom', + bottom: '8rem', + }) + } + > + <Button size="small" variants="secondary"> + ์ •์‚ฐ ์ดˆ๋Œ€ํ•˜๊ธฐ + </Button> + </CopyToClipboard> + )} + </TopNav> + <Outlet context={outletContext} /> + </MainLayout> + ); +}; + +export default EventPageLayout; diff --git a/client/src/pages/EventPage/HomePage/HomePage.tsx b/client/src/pages/EventPage/HomePage/HomePage.tsx new file mode 100644 index 000000000..72fc77cb9 --- /dev/null +++ b/client/src/pages/EventPage/HomePage/HomePage.tsx @@ -0,0 +1,26 @@ +import {Tab, Tabs, Title} from 'haengdong-design'; +import {useOutletContext} from 'react-router-dom'; + +import MemberReportList from '@components/MemberReportList/MemberReportList'; +import StepList from '@components/StepList/StepList'; + +import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; + +import {EventPageContextProps} from '../EventPageLayout'; + +const HomePage = () => { + const {eventName} = useOutletContext<EventPageContextProps>(); + const {totalExpenseAmount} = useTotalExpenseAmountStore(); + + return ( + <div style={{paddingBottom: '2rem'}}> + <Title title={eventName} price={totalExpenseAmount} /> + <Tabs tabsContainerStyle={{gap: '1rem'}}> + <Tab label="์ „์ฒด ์ง€์ถœ ๋‚ด์—ญ" content={<StepList />} /> + <Tab label="์ฐธ์—ฌ์ž ๋ณ„ ๋‚ด์—ญ" content={<MemberReportList />} /> + </Tabs> + </div> + ); +}; + +export default HomePage; diff --git a/client/src/pages/EventPage/HomePage/index.ts b/client/src/pages/EventPage/HomePage/index.ts new file mode 100644 index 000000000..aa0bf2b3f --- /dev/null +++ b/client/src/pages/EventPage/HomePage/index.ts @@ -0,0 +1 @@ +export {default as HomePage} from './HomePage'; diff --git a/client/src/pages/EventPage/index.ts b/client/src/pages/EventPage/index.ts new file mode 100644 index 000000000..5b5c314c7 --- /dev/null +++ b/client/src/pages/EventPage/index.ts @@ -0,0 +1 @@ +export {default as EventPage} from './EventPageLayout'; diff --git a/client/src/pages/MainPage/MainPage.tsx b/client/src/pages/MainPage/MainPage.tsx new file mode 100644 index 000000000..d3a1cd079 --- /dev/null +++ b/client/src/pages/MainPage/MainPage.tsx @@ -0,0 +1,23 @@ +import {MainLayout} from 'haengdong-design'; + +import Nav from './Nav/Nav'; +import MainSection from './Section/MainSection'; +import DescriptionSection from './Section/DescriptionSection'; +import AddBillSection from './Section/AddBillSection'; +import AddMemberSection from './Section/AddMemberSection'; +import MemberReportSection from './Section/MemberReportSection'; + +const MainPage = () => { + return ( + <MainLayout> + <Nav /> + <MainSection /> + <DescriptionSection /> + <AddBillSection /> + <AddMemberSection /> + <MemberReportSection /> + </MainLayout> + ); +}; + +export default MainPage; diff --git a/client/src/pages/MainPage/Nav/Nav.style.ts b/client/src/pages/MainPage/Nav/Nav.style.ts new file mode 100644 index 000000000..58cf1cb86 --- /dev/null +++ b/client/src/pages/MainPage/Nav/Nav.style.ts @@ -0,0 +1,22 @@ +import {css} from '@emotion/react'; + +export const navStyle = css({ + position: 'fixed', + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + padding: '1rem', + + top: '0', + width: '100%', + maxWidth: '768px', + zIndex: '20', + height: '4rem', + backgroundColor: 'white', +}); + +export const logoStyle = css({ + display: 'flex', + gap: '0.5rem', + alignItems: 'center', +}); diff --git a/client/src/pages/MainPage/Nav/Nav.tsx b/client/src/pages/MainPage/Nav/Nav.tsx new file mode 100644 index 000000000..ec4d745c9 --- /dev/null +++ b/client/src/pages/MainPage/Nav/Nav.tsx @@ -0,0 +1,27 @@ +import {Button, Flex, Text} from 'haengdong-design'; +import {useNavigate} from 'react-router-dom'; + +import Heundeut from '@assets/image/heundeut.svg'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +import {logoStyle, navStyle} from './Nav.style'; + +const Nav = () => { + const navigate = useNavigate(); + return ( + <header css={navStyle}> + <Flex gap="0.5rem"> + <Heundeut /> + <div css={logoStyle}> + <Text size="subTitle">ํ–‰๋™๋Œ€์žฅ</Text> + </div> + </Flex> + <Button size="medium" variants="tertiary" onClick={() => navigate(ROUTER_URLS.eventCreateName)}> + ์ •์‚ฐ ์‹œ์ž‘ํ•˜๊ธฐ + </Button> + </header> + ); +}; + +export default Nav; diff --git a/client/src/pages/MainPage/Section/AddBillSection.tsx b/client/src/pages/MainPage/Section/AddBillSection.tsx new file mode 100644 index 000000000..ecf7dd90d --- /dev/null +++ b/client/src/pages/MainPage/Section/AddBillSection.tsx @@ -0,0 +1,31 @@ +import {css} from '@emotion/react'; +import {Text} from 'haengdong-design'; + +import AddBillMockup from '@assets/image/addBillMockup.svg'; + +const AddBillSection = () => { + return ( + <div + css={css({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + padding: '3rem', + gap: '2rem', + width: '100%', + backgroundColor: 'white', + })} + > + <div css={css({display: 'flex', flexDirection: 'column', gap: '1rem'})}> + <Text size="subTitle">์ง€์ถœ๋‚ด์—ญ์„ ์‰ฝ๊ฒŒ ์ถ”๊ฐ€ํ•˜์„ธ์š”</Text> + <Text size="body" textColor="gray"> + {`๋‚˜์ค‘์— ํ•œ๋ฒˆ์— ๊ธฐ๋กํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ, + ์‹ค์‹œ๊ฐ„์œผ๋กœ ๊ธฐ๋กํ•ด ๋†“์„ ์ˆ˜ ์žˆ์–ด์š”`} + </Text> + </div> + <AddBillMockup /> + </div> + ); +}; + +export default AddBillSection; diff --git a/client/src/pages/MainPage/Section/AddMemberSection.tsx b/client/src/pages/MainPage/Section/AddMemberSection.tsx new file mode 100644 index 000000000..ae6e7d1fc --- /dev/null +++ b/client/src/pages/MainPage/Section/AddMemberSection.tsx @@ -0,0 +1,33 @@ +import {css} from '@emotion/react'; +import {Text} from 'haengdong-design'; +import {useTheme} from 'haengdong-design/dist/theme/HDesignProvider'; + +import AddMemberMockup from '@assets/image/addMemberMockup.svg'; + +const AddMemberSection = () => { + const {theme} = useTheme(); + return ( + <div + css={css({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + padding: '3rem', + gap: '2rem', + width: '100%', + backgroundColor: theme.colors.lightGrayContainer, + })} + > + <div css={css({display: 'flex', flexDirection: 'column', gap: '1rem'})}> + <Text size="subTitle">์ธ์› ๋ณ€๋™์€ ์‹ ๊ฒฝ์“ฐ์ง€ ๋งˆ์„ธ์š”</Text> + <Text size="body" textColor="gray"> + {`๋ˆ„๊ฐ€ ๋‚˜๊ฐ€๊ณ  ๋“ค์–ด์™”๋Š”์ง€๋งŒ ๊ธฐ๋กํ•˜์„ธ์š” + ํ–‰๋™๋Œ€์žฅ์ด ์•Œ์•„์„œ ์ฐจ์ˆ˜๋ฅผ ๋‚˜๋ˆ ์ค˜์š”`} + </Text> + </div> + <AddMemberMockup /> + </div> + ); +}; + +export default AddMemberSection; diff --git a/client/src/pages/MainPage/Section/DescriptionSection.tsx b/client/src/pages/MainPage/Section/DescriptionSection.tsx new file mode 100644 index 000000000..193cfe465 --- /dev/null +++ b/client/src/pages/MainPage/Section/DescriptionSection.tsx @@ -0,0 +1,33 @@ +import {css} from '@emotion/react'; +import {Text} from 'haengdong-design'; +import {useTheme} from 'haengdong-design/dist/theme/HDesignProvider'; + +const DescriptionSection = () => { + const {theme} = useTheme(); + + return ( + <div + css={css({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + width: '100%', + gap: '1.5rem', + padding: '3rem 1.5rem', + backgroundColor: theme.colors.lightGrayContainer, + })} + > + <Text style={{textAlign: 'center'}} size="subTitle">{`ํ–‰๋™๋Œ€์žฅ๋“ค์„ ์œ„ํ•ด + ํ–‰๋™๋Œ€์žฅ์„ ์ค€๋น„ํ–ˆ์–ด์š” + `}</Text> + <Text style={{textAlign: 'center'}} size="subTitle" textColor="gray">{`์ฃผํ™˜์ด๊ฐ€ ๋จผ์ € ์ง‘์— ๊ฐ€๋„ + ์†Œ์—ฐ์ด๊ฐ€ ๋Šฆ๊ฒŒ ๋„์ฐฉํ•ด๋„ + ๊ฑด์ƒ์ด๊ฐ€ ์ˆ ์„ ๋งˆ์‹œ์ง€ ์•Š์•„๋„ + `}</Text> + <Text style={{textAlign: 'center'}} size="subTitle">{`๊ฐ„ํŽธํ•˜๊ฒŒ ์ •์‚ฐํ•  ์ˆ˜ ์žˆ์–ด์š”`}</Text> + </div> + ); +}; + +export default DescriptionSection; diff --git a/client/src/pages/MainPage/Section/MainSection.tsx b/client/src/pages/MainPage/Section/MainSection.tsx new file mode 100644 index 000000000..4bbeb7340 --- /dev/null +++ b/client/src/pages/MainPage/Section/MainSection.tsx @@ -0,0 +1,93 @@ +import {css, keyframes} from '@emotion/react'; +import {Button, Text} from 'haengdong-design'; +import {useNavigate} from 'react-router-dom'; + +import {StandingDog} from '@components/Common/Logo'; +import ChevronDown from '@assets/image/chevronDownLarge.svg'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +const MainSection = () => { + const navigate = useNavigate(); + return ( + <div + css={css({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + height: '100vh', + width: '100%', + backgroundColor: 'white', + })} + > + <div + css={css({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + gap: '2rem', + padding: '1.5rem', + height: '100vh', + width: '100%', + })} + > + <div css={animateWithDelay(0)}> + <StandingDog /> + </div> + <Text css={animateWithDelay(1)} style={{textAlign: 'center'}} size="title">{`ํ–‰๋™๋Œ€์žฅ์„ ํ†ตํ•ด + ๊ฐ„ํŽธํ•˜๊ฒŒ ์ •์‚ฐํ•˜์„ธ์š” + `}</Text> + <Button css={animateWithDelay(2)} size="large" onClick={() => navigate(ROUTER_URLS.eventCreateName)}> + ์ •์‚ฐ ์‹œ์ž‘ํ•˜๊ธฐ + </Button> + </div> + <div + css={css({ + position: 'absolute', + bottom: '2rem', + left: '50%', + animation: `${bounce} 2s infinite ease-in-out`, + })} + > + <ChevronDown /> + </div> + </div> + ); +}; + +const fadeIn = keyframes` + from { + opacity: 0; + } + to { + opacity: 1; + } +`; + +const slideIn = keyframes` + from { + transform: translateY(1rem); + } + to { + transform: translateY(0); + } +`; + +const bounce = keyframes` + 0%, 100% { + transform: translate(-50%, 0); + } + 50% { + transform: translate(-50%, -1rem); + } +`; + +const animateWithDelay = (delay: number) => css` + opacity: 0; + animation: + ${fadeIn} 1s ease-in-out ${delay}s forwards, + ${slideIn} 1s ease-in-out ${delay}s forwards; +`; + +export default MainSection; diff --git a/client/src/pages/MainPage/Section/MemberReportSection.tsx b/client/src/pages/MainPage/Section/MemberReportSection.tsx new file mode 100644 index 000000000..69871e1c9 --- /dev/null +++ b/client/src/pages/MainPage/Section/MemberReportSection.tsx @@ -0,0 +1,31 @@ +import {css} from '@emotion/react'; +import {Text} from 'haengdong-design'; + +import MemberReportMockup from '@assets/image/memberReportMockup.svg'; + +const MemberReportSection = () => { + return ( + <div + css={css({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + padding: '3rem', + gap: '2rem', + width: '100%', + backgroundColor: 'white', + })} + > + <div css={css({display: 'flex', flexDirection: 'column', gap: '1rem'})}> + <Text size="subTitle">์นœ๊ตฌ์—๊ฒŒ ๋งํฌ๋ฅผ ๊ณต์œ ํ•˜์„ธ์š”</Text> + <Text size="body" textColor="gray"> + {`์ง€์ถœ๋‚ด์—ญ๊ณผ ์ธ์›๋ณ€๋™์„ ํ†ตํ•ด + ๊ธˆ์•ก์€ ์ž๋™์œผ๋กœ ๊ณ„์‚ฐ๋ผ์š”`} + </Text> + </div> + <MemberReportMockup /> + </div> + ); +}; + +export default MemberReportSection; diff --git a/client/src/pages/MainPage/index.ts b/client/src/pages/MainPage/index.ts new file mode 100644 index 000000000..017fff307 --- /dev/null +++ b/client/src/pages/MainPage/index.ts @@ -0,0 +1 @@ +export {default as MainPage} from './MainPage'; diff --git a/client/src/router.tsx b/client/src/router.tsx new file mode 100644 index 000000000..51162c775 --- /dev/null +++ b/client/src/router.tsx @@ -0,0 +1,58 @@ +import {createBrowserRouter} from 'react-router-dom'; + +import {AdminPage} from '@pages/EventPage/AdminPage'; +import {HomePage} from '@pages/EventPage/HomePage'; +import ErrorPage from '@pages/ErrorPage/ErrorPage'; +import EventLoginPage from '@pages/EventPage/AdminPage/EventLoginPage'; + +import {CompleteCreateEventPage, SetEventNamePage, SetEventPasswordPage} from '@pages/CreateEventPage'; +import {MainPage} from '@pages/MainPage'; +import {EventPage} from '@pages/EventPage'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +import App from './App'; + +const router = createBrowserRouter([ + { + path: '', + element: <App />, + children: [ + { + index: true, + path: ROUTER_URLS.main, + element: <MainPage />, + }, + { + path: ROUTER_URLS.eventCreateName, + element: <SetEventNamePage />, + }, + { + path: ROUTER_URLS.eventCreatePassword, + element: <SetEventPasswordPage />, + }, + { + path: ROUTER_URLS.eventCreateComplete, + element: <CompleteCreateEventPage />, + }, + { + path: ROUTER_URLS.event, + element: <EventPage />, + children: [ + {path: ROUTER_URLS.eventManage, element: <AdminPage />}, + {path: ROUTER_URLS.home, element: <HomePage />}, + { + path: ROUTER_URLS.eventLogin, + element: <EventLoginPage />, + }, + ], + }, + { + path: '*', + element: <ErrorPage />, + }, + ], + }, +]); + +export default router; diff --git a/client/src/store/appErrorStore.ts b/client/src/store/appErrorStore.ts new file mode 100644 index 000000000..ca350d4cb --- /dev/null +++ b/client/src/store/appErrorStore.ts @@ -0,0 +1,14 @@ +import {create} from 'zustand'; + +type State = { + appError: Error | null; +}; + +type Action = { + updateAppError: (appError: State['appError']) => void; +}; + +export const useAppErrorStore = create<State & Action>(set => ({ + appError: null, + updateAppError: appError => set(() => ({appError})), +})); diff --git a/client/src/store/stepListStore.ts b/client/src/store/stepListStore.ts new file mode 100644 index 000000000..07f3b107f --- /dev/null +++ b/client/src/store/stepListStore.ts @@ -0,0 +1,16 @@ +import {create} from 'zustand'; + +import {ConvertedAction} from 'types/serviceType'; + +type State = { + stepList: ConvertedAction[]; +}; + +type Action = { + updateStepList: (stepList: State['stepList']) => void; +}; + +export const useStepListStore = create<State & Action>(set => ({ + stepList: [], + updateStepList: stepList => set(() => ({stepList})), +})); diff --git a/client/src/store/totalExpenseAmountStore.ts b/client/src/store/totalExpenseAmountStore.ts new file mode 100644 index 000000000..e9ebcf52a --- /dev/null +++ b/client/src/store/totalExpenseAmountStore.ts @@ -0,0 +1,18 @@ +import {create} from 'zustand'; + +import {BillStep, MemberStep} from 'types/serviceType'; + +import {getTotalExpenseAmount} from '@utils/caculateExpense'; + +type State = { + totalExpenseAmount: number; +}; + +type Action = { + updateTotalExpenseAmount: (stepList: (MemberStep | BillStep)[]) => void; +}; + +export const useTotalExpenseAmountStore = create<State & Action>(set => ({ + totalExpenseAmount: 0, + updateTotalExpenseAmount: stepList => set({totalExpenseAmount: getTotalExpenseAmount(stepList)}), +})); diff --git a/client/src/types/fetchErrorType.ts b/client/src/types/fetchErrorType.ts new file mode 100644 index 000000000..19fe8ee6f --- /dev/null +++ b/client/src/types/fetchErrorType.ts @@ -0,0 +1,11 @@ +import {ErrorInfo} from '@components/AppErrorBoundary/ErrorCatcher'; + +import {Method} from '@apis/fetcher'; + +export type FetchErrorType = Error & { + requestBody: string; + status: number; + endpoint: string; + errorInfo: ErrorInfo; + method: Method; +}; diff --git a/client/src/types/serviceType.ts b/client/src/types/serviceType.ts new file mode 100644 index 000000000..0467995f1 --- /dev/null +++ b/client/src/types/serviceType.ts @@ -0,0 +1,80 @@ +export type MemberType = 'IN' | 'OUT'; + +export type InOutType = '๋Šฆ์ฐธ' | 'ํƒˆ์ฃผ'; + +export type MemberReport = { + name: string; + price: number; +}; + +export type MemberReportInAction = MemberReport & { + isFixed: boolean; +}; + +export type Bill = { + title: string; + price: number; +}; + +type StepBase = { + members: string[]; +}; + +export type MemberStep = StepBase & { + type: MemberType; + stepName: null; + actions: MemberAction[]; +}; + +export type BillStep = StepBase & { + type: 'BILL'; + stepName: string; + actions: BillAction[]; +}; + +// (@weadie) ์ค€ ๋ฐ์ดํ„ฐ ํ˜•์‹์—์„œ steps๋ฅผ ๋นผ๋‚ด flatํ•˜๊ฒŒ ์‚ฌ์šฉ์ค‘. ์ผ๊ด€์„ฑ์žˆ๊ฒŒ ํ•˜๋Š”๊ฒŒ ์ข‹๊ธด ํ•˜๋‚˜ ์‚ฌ์šฉ์‹œ ๋ฒˆ๊ฑฐ๋กœ์›€์ด ์žˆ์„ ๊ฑฐ๋ผ๊ณ  ํŒ๋‹จ. +export type StepList = { + steps: (MemberStep | BillStep)[]; +}; + +export type Action = { + actionId: number; + name: string; + price: number | null; + sequence: number; + isFixed: boolean; +}; + +export type BillAction = Omit<Action, 'price'> & { + price: number; +}; + +export type MemberAction = Omit<Action, 'price'> & { + price: null; +}; + +export type Member = { + name: string; + status: MemberType; +}; + +export type ActionType = 'IN' | 'OUT' | 'BILL'; + +// export type StepList = { +// actions: Action[]; +// }; + +export type ConvertedAction = { + actionId: number; + name: string; + price: string | null; + sequence: number; + type: ActionType; +}; + +export type InputPair = Omit<Bill, 'price'> & { + price: string; + index: number; +}; + +export type BillInputType = 'title' | 'price'; diff --git a/client/src/utils/caculateExpense.ts b/client/src/utils/caculateExpense.ts new file mode 100644 index 000000000..8b41af8c3 --- /dev/null +++ b/client/src/utils/caculateExpense.ts @@ -0,0 +1,14 @@ +import {BillAction, BillStep, MemberStep} from 'types/serviceType'; + +export const calculateStepExpense = (actions: BillAction[]) => { + return actions.reduce((sum, {price}) => sum + price, 0); +}; + +export const getTotalExpenseAmount = (stepList: (MemberStep | BillStep)[]) => { + return stepList.reduce((sum, {type, actions}) => { + if (type === 'BILL') { + return sum + calculateStepExpense(actions); + } + return sum; + }, 0); +}; diff --git a/client/src/utils/captureError.ts b/client/src/utils/captureError.ts new file mode 100644 index 000000000..67a30ac99 --- /dev/null +++ b/client/src/utils/captureError.ts @@ -0,0 +1,49 @@ +import {ErrorInfo} from '@components/AppErrorBoundary/ErrorCatcher'; + +import sendLogToSentry from './sendLogToSentry'; + +export const captureError = async (error: Error, errorInfo: ErrorInfo) => { + // prod ํ™˜๊ฒฝ์—์„œ๋งŒ Sentry capture ์‹คํ–‰ + if (process.env.NODE_ENV !== 'production') return; + + switch (errorInfo?.errorCode) { + case 'INTERNAL_SERVER_ERROR': + sendLogToSentry({error, errorInfo, level: 'fatal'}); + break; + + case 'FORBIDDEN': + sendLogToSentry({error, errorInfo}); + + break; + + case 'TOKEN_INVALID': + sendLogToSentry({error, errorInfo}); + + break; + + case 'TOKEN_EXPIRED': + sendLogToSentry({error, errorInfo}); + + break; + + case 'TOKEN_NOT_FOUND': + sendLogToSentry({error, errorInfo}); + + break; + + // ๋น„๋ฐ€ ๋ฒˆํ˜ธ๋ฅผ ๊นŒ๋จน๋Š” ์‚ฌ๋žŒ์ด ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ์ง€ ์ถ”์ธกํ•˜๊ธฐ ์œ„ํ•จ + case 'PASSWORD_INVALID': + sendLogToSentry({error, errorInfo, level: 'debug'}); + + break; + + // 1์ฒœ๋งŒ์› ์ด์ƒ ์ž…๋ ฅํ•˜๋Š” ์‚ฌ๋žŒ์ด ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ์ง€ ์ถ”์ธกํ•˜๊ธฐ ์œ„ํ•จ + case 'BILL_ACTION_PRICE_INVALID': + sendLogToSentry({error, errorInfo, level: 'debug'}); + break; + + default: + sendLogToSentry({error, errorInfo, level: 'fatal'}); + break; + } +}; diff --git a/client/src/utils/getEventIdByUrl.ts b/client/src/utils/getEventIdByUrl.ts new file mode 100644 index 000000000..1cdb16c8f --- /dev/null +++ b/client/src/utils/getEventIdByUrl.ts @@ -0,0 +1,13 @@ +import REGEXP from '@constants/regExp'; + +const extractEventIdFromUrl = (url: string) => { + const regex = REGEXP.eventUrl; + const match = url.match(regex); + return match ? match[1] : null; +}; + +const getEventIdByUrl = () => { + return extractEventIdFromUrl(window.location.pathname) ?? ''; +}; + +export default getEventIdByUrl; diff --git a/client/src/utils/getEventPageUrlByEnvironment.ts b/client/src/utils/getEventPageUrlByEnvironment.ts new file mode 100644 index 000000000..bcfce54e9 --- /dev/null +++ b/client/src/utils/getEventPageUrlByEnvironment.ts @@ -0,0 +1,11 @@ +import {ROUTER_URLS} from '@constants/routerUrls'; + +type EventPageTab = 'home' | 'admin'; + +const getEventPageUrlByEnvironment = (eventId: string, tab: EventPageTab) => { + const isDevelopment = process.env.NODE_ENV === 'development'; + + return `https://${isDevelopment ? 'dev.' : ''}haengdong.pro${ROUTER_URLS.event}/${eventId}/${tab}`; +}; + +export default getEventPageUrlByEnvironment; diff --git a/client/src/utils/groupActions.ts b/client/src/utils/groupActions.ts new file mode 100644 index 000000000..a6347167d --- /dev/null +++ b/client/src/utils/groupActions.ts @@ -0,0 +1,27 @@ +import {BillStep, ConvertedAction, MemberStep} from 'types/serviceType'; + +import stepListToAction from './stepListToActions'; + +const groupActions = (stepList: (BillStep | MemberStep)[]) => { + const actions = stepListToAction(stepList); + const groupedActions: ConvertedAction[][] = []; + + let group: ConvertedAction[] = []; + + actions.forEach((action, index) => { + if (group.length === 0 || group[group.length - 1].type === action.type) { + group.push(action); + } else { + groupedActions.push(group); + group = []; + } + + if (index === actions.length - 1) { + groupedActions.push(group); + } + }); + + return groupedActions; +}; + +export default groupActions; diff --git a/client/src/utils/isArraysEqual.ts b/client/src/utils/isArraysEqual.ts new file mode 100644 index 000000000..df73a8552 --- /dev/null +++ b/client/src/utils/isArraysEqual.ts @@ -0,0 +1,16 @@ +const isArraysEqual = <T>(arr1: T[], arr2: T[]) => { + if (arr1.length !== arr2.length) return false; + + // ๋ฐฐ์—ด์„ ์ •๋ ฌํ•œ ํ›„ ๋น„๊ต + const sortedArr1 = [...arr1].sort(); + const sortedArr2 = [...arr2].sort(); + + // ๊ฐ’์€ ๋ชจ๋‘ ๊ฐ™์œผ๋‚˜ ์ˆœ์„œ๋ฅผ ๋ณ€๊ฒฝํ–ˆ์„ ์‹œ, false๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. + for (let i = 0; i < sortedArr1.length; i++) { + if (sortedArr1[i] !== sortedArr2[i]) return false; + } + + return true; +}; + +export default isArraysEqual; diff --git a/client/src/utils/objectToQueryString.ts b/client/src/utils/objectToQueryString.ts new file mode 100644 index 000000000..cc40fb076 --- /dev/null +++ b/client/src/utils/objectToQueryString.ts @@ -0,0 +1,9 @@ +import {ObjectQueryParams} from '@apis/fetcher'; + +const objectToQueryString = (params: ObjectQueryParams): string => { + return Object.entries(params) + .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`) + .join('&'); +}; + +export default objectToQueryString; diff --git a/client/src/utils/sendLogToSentry.ts b/client/src/utils/sendLogToSentry.ts new file mode 100644 index 000000000..22d736b6c --- /dev/null +++ b/client/src/utils/sendLogToSentry.ts @@ -0,0 +1,66 @@ +import * as Sentry from '@sentry/react'; + +import {ErrorInfo} from '@components/AppErrorBoundary/ErrorCatcher'; + +import {UNKNOWN_ERROR} from '@constants/errorMessage'; + +import FetchError from '../errors/FetchError'; + +/** + * level์€ ์•„๋ž˜์™€ ๊ฐ™์€ ์šฉ๋„์— ๋งž๊ฒŒ ์ง€์ •ํ•ด์ค๋‹ˆ๋‹ค. + * + * fatal: ์•ฑ์ด ์ข…๋ฃŒ๋  ์ˆ˜ ์žˆ๋Š” ์น˜๋ช…์ ์ธ ์˜ค๋ฅ˜ + * error: ํŠน์ • ๊ธฐ๋Šฅ ์‹คํŒจ๋กœ ์•ฑ ์ข…๋ฃŒ๊นŒ์ง€๋Š” ์•„๋‹Œ ์˜ค๋ฅ˜ + * warning: ์ž ์žฌ์ ์œผ๋กœ ๋ฌธ์ œ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋Š” ์˜ค๋ฅ˜. ํ˜„์žฌ๋Š” ์‹ฌ๊ฐํ•˜์ง€ ์•Š์€ ์˜ค๋ฅ˜ + * info: ์‹œ์Šคํ…œ์˜ ์ •์ƒ์ ์ธ ๋™์ž‘์„ ๋‚˜ํƒ€๋ƒ„. ์ค‘์š”ํ•œ ์ด๋ฒคํŠธ๋‚˜ ์ƒํƒœ ๋ณ€ํ™” ๊ธฐ๋ก์šฉ + * debug: ๋””๋ฒ„๊น… ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉ๋จ + * log: ์ผ๋ฐ˜์ ์ธ ๋กœ๊ทธ ๋ฉ”์„ธ์ง€ + */ + +type SentryLevel = 'fatal' | 'error' | 'warning' | 'info' | 'debug' | 'log'; +type SendLogToSentry = { + level?: SentryLevel; + error: Error; + errorInfo: ErrorInfo; +}; + +const sendLogToSentry = ({level = 'error', error, errorInfo}: SendLogToSentry) => { + Sentry.withScope(scope => { + const {errorCode, message} = errorInfo; + scope.setLevel(level); + + scope.setTag('environment', process.env.NODE_ENV); + + if (error instanceof FetchError) { + scope.setTags({ + endpoint: error.endpoint, + url: window.location.href, + errorCode, + errorMessage: message, + status: error.status, + // requestBody: JSON.stringify(error.requestBody), + method: error.method, + }); + + Sentry.captureMessage(`${errorCode}`); + } else if (error instanceof Error) { + scope.setTags({ + url: window.location.href, + errorCode, + errorMessage: message, + }); + + Sentry.captureMessage(`${errorCode}`); + } else { + scope.setTags({ + url: window.location.href, + errorCode, + message: UNKNOWN_ERROR, + name: UNKNOWN_ERROR, + }); + Sentry.captureMessage(`${errorCode}`); + } + }); +}; + +export default sendLogToSentry; diff --git a/client/src/utils/stepListToActions.ts b/client/src/utils/stepListToActions.ts new file mode 100644 index 000000000..5fe1bb3a7 --- /dev/null +++ b/client/src/utils/stepListToActions.ts @@ -0,0 +1,23 @@ +import {BillStep, ConvertedAction, MemberStep} from 'types/serviceType'; + +const stepListToAction = (stepList: (BillStep | MemberStep)[]) => { + // (@todari) test์šฉ์ด๋ผ ์ž„์‹œ๋กœ any ์‚ฌ์šฉํ• ๊ฒŒ์šฉ... + // Action์„ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•˜๋Š”๋ฐ serviceType์˜ ๊ธฐ์กด Action์ด๋ž‘ ๊ฒน์ณ์„œ์š”~~~ + const actions: ConvertedAction[] = []; + + stepList.forEach(step => { + step.actions.forEach(action => { + actions.push({ + actionId: action.actionId, + name: action.name, + price: action.price ? action.price.toLocaleString() : null, + sequence: action.sequence, + type: step.type, + }); + }); + }); + + return actions; +}; + +export default stepListToAction; diff --git a/client/src/utils/validate/type.ts b/client/src/utils/validate/type.ts new file mode 100644 index 000000000..df81f1644 --- /dev/null +++ b/client/src/utils/validate/type.ts @@ -0,0 +1,5 @@ +export interface ValidateResult { + isValid: boolean; + errorMessage: string | null; + errorInfo?: Record<string, boolean>; +} diff --git a/client/src/utils/validate/validateEventName.ts b/client/src/utils/validate/validateEventName.ts new file mode 100644 index 000000000..93f4ecef1 --- /dev/null +++ b/client/src/utils/validate/validateEventName.ts @@ -0,0 +1,13 @@ +import {ERROR_MESSAGE} from '@constants/errorMessage'; +import RULE from '@constants/rule'; + +import {ValidateResult} from './type'; + +const validateEventName = (name: string): ValidateResult => { + if (name.length > RULE.maxEventNameLength) { + return {isValid: false, errorMessage: ERROR_MESSAGE.eventName}; + } + return {isValid: true, errorMessage: null}; +}; + +export default validateEventName; diff --git a/client/src/utils/validate/validateEventPassword.ts b/client/src/utils/validate/validateEventPassword.ts new file mode 100644 index 000000000..7075e2f3e --- /dev/null +++ b/client/src/utils/validate/validateEventPassword.ts @@ -0,0 +1,13 @@ +import {ERROR_MESSAGE} from '@constants/errorMessage'; +import REGEXP from '@constants/regExp'; + +import {ValidateResult} from './type'; + +const validateEventPassword = (password: string): ValidateResult => { + if (!REGEXP.eventPassword.test(password)) { + return {isValid: false, errorMessage: ERROR_MESSAGE.eventPasswordType}; + } + return {isValid: true, errorMessage: null}; +}; + +export default validateEventPassword; diff --git a/client/src/utils/validate/validateMemberName.ts b/client/src/utils/validate/validateMemberName.ts new file mode 100644 index 000000000..bb87122a2 --- /dev/null +++ b/client/src/utils/validate/validateMemberName.ts @@ -0,0 +1,34 @@ +import REGEXP from '@constants/regExp'; +import {ERROR_MESSAGE} from '@constants/errorMessage'; +import RULE from '@constants/rule'; + +import {ValidateResult} from './type'; + +const validateMemberName = (name: string): ValidateResult => { + let errorMessage = null; + const validateOnlyString = () => { + if (!REGEXP.memberName.test(name)) return false; + return true; + }; + + const validateLength = () => { + if (name.length > RULE.maxMemberNameLength) return false; + return true; + }; + + const validateEmpty = () => { + if (!name.trim().length) { + errorMessage = ERROR_MESSAGE.preventEmpty; + return false; + } + return true; + }; + + if (validateOnlyString() && validateLength() && validateEmpty()) { + return {isValid: true, errorMessage: null}; + } + + return {isValid: false, errorMessage: errorMessage || ERROR_MESSAGE.memberName}; +}; + +export default validateMemberName; diff --git a/client/src/utils/validate/validateMemberReportInAction.ts b/client/src/utils/validate/validateMemberReportInAction.ts new file mode 100644 index 000000000..b4e6c2a9a --- /dev/null +++ b/client/src/utils/validate/validateMemberReportInAction.ts @@ -0,0 +1,33 @@ +import {ERROR_MESSAGE} from '@constants/errorMessage'; +import RULE from '@constants/rule'; + +import {ValidateResult} from './type'; + +const validateMemberReportInAction = (price: string, totalPrice: number): ValidateResult => { + let errorMessage = null; + const numberTypePrice = Number(price); + + const validateOnlyNaturalNumber = () => { + if (!(Number.isInteger(numberTypePrice) && numberTypePrice >= 0)) return false; + return true; + }; + + const validatePrice = () => { + if (numberTypePrice > RULE.maxPrice) return false; + return true; + }; + + const validateUnderTotalPrice = () => { + if (numberTypePrice > totalPrice) return false; + + return true; + }; + + if (validateOnlyNaturalNumber() && validatePrice() && validateUnderTotalPrice()) { + return {isValid: true, errorMessage: null}; + } + + return {isValid: false, errorMessage: errorMessage || ERROR_MESSAGE.invalidInput}; +}; + +export default validateMemberReportInAction; diff --git a/client/src/utils/validate/validatePurchase.ts b/client/src/utils/validate/validatePurchase.ts new file mode 100644 index 000000000..9915ce8b7 --- /dev/null +++ b/client/src/utils/validate/validatePurchase.ts @@ -0,0 +1,47 @@ +import type {Bill} from 'types/serviceType'; + +import {ERROR_MESSAGE} from '@constants/errorMessage'; +import RULE from '@constants/rule'; +import REGEXP from '@constants/regExp'; + +import {ValidateResult} from './type'; + +const validatePurchase = (inputPair: Bill): ValidateResult => { + const {title, price} = inputPair; + let errorMessage: string | null = null; + + const errorInfo = { + price: false, + title: false, + }; + + const validatePrice = () => { + if (price > RULE.maxPrice) { + errorMessage = ERROR_MESSAGE.purchasePrice; + errorInfo.price = true; + return false; + } + + errorInfo.price = false; + return true; + }; + + const validateTitle = () => { + if (!REGEXP.purchaseTitle.test(title)) { + errorMessage = ERROR_MESSAGE.purchaseTitle; + errorInfo.title = true; + return false; + } + + errorInfo.title = false; + return true; + }; + + if (validatePrice() && validateTitle()) { + return {isValid: true, errorMessage: null}; + } + + return {isValid: false, errorMessage, errorInfo}; +}; + +export default validatePurchase; diff --git a/client/tsconfig.json b/client/tsconfig.json new file mode 100644 index 000000000..84c7c054a --- /dev/null +++ b/client/tsconfig.json @@ -0,0 +1,53 @@ +{ + "compilerOptions": { + "sourceMap": true, + "module": "ES2020", + "target": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "useDefineForClassFields": true, + "removeComments": true, + "skipLibCheck": true, + + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + + "jsx": "react-jsx", + "strict": true, + // "noUnusedLocals": true, + // "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + + "types": ["jest", "@testing-library/jest-dom", "node", "cypress"], + "esModuleInterop": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "strictPropertyInitialization": true, + "noImplicitAny": true, + "noImplicitThis": true, + "alwaysStrict": true, + "noImplicitReturns": true, + "forceConsistentCasingInFileNames": true, + "jsxImportSource": "@emotion/react", + + "baseUrl": "./src", + "paths": { + "@apis/*": ["apis/*"], + "@assets/*": ["assets/*"], + "@components/*": ["components/*"], + "@constants/*": ["constants/*"], + "@store/*": ["store/*"], + "@hooks/*": ["hooks/*"], + "@mocks/*": ["mocks/*"], + "@pages/*": ["pages/*"], + "@utils/*": ["utils/*"], + "@errors/*": ["errors/*"] + }, + "outDir": "./dist" + }, + "node": true, + "include": ["src", "jest.config.ts", "jest.setup.ts", "cypress/**/*.ts"] +} diff --git a/client/webpack.common.mjs b/client/webpack.common.mjs new file mode 100644 index 000000000..160baf0ca --- /dev/null +++ b/client/webpack.common.mjs @@ -0,0 +1,60 @@ +import path from 'path'; +import HtmlWebpackPlugin from 'html-webpack-plugin'; +import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; +import {ModifySourcePlugin, ConcatOperation} from 'modify-source-webpack-plugin'; +import {fileURLToPath} from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +export default { + entry: './src/index.tsx', + resolve: { + extensions: ['.js', '.jsx', '.ts', '.tsx'], + alias: { + '@apis': path.resolve(__dirname, 'src/apis/'), + '@assets': path.resolve(__dirname, 'src/assets/'), + '@components': path.resolve(__dirname, 'src/components/'), + '@constants': path.resolve(__dirname, 'src/constants/'), + '@hooks': path.resolve(__dirname, 'src/hooks/'), + '@store': path.resolve(__dirname, 'src/store/'), + '@mocks': path.resolve(__dirname, 'src/mocks/'), + '@pages': path.resolve(__dirname, 'src/pages/'), + '@utils': path.resolve(__dirname, 'src/utils/'), + '@errors': path.resolve(__dirname, 'src/errors/'), + }, + }, + module: { + rules: [ + { + test: /\.tsx?$/, + loader: 'ts-loader', + exclude: /node_modules/, + }, + { + test: /\.svg$/, + use: [ + { + loader: '@svgr/webpack', + }, + ], + }, + ], + }, + plugins: [ + new HtmlWebpackPlugin({ + template: './index.html', + hash: true, + favicon: './favicon.ico', + }), + new ForkTsCheckerWebpackPlugin(), + new ModifySourcePlugin({ + rules: [ + { + test: /\.tsx$/i, + operations: [new ConcatOperation('start', '/** @jsxImportSource @emotion/react */\n\n')], + }, + ], + }), + ], +}; diff --git a/client/webpack.dev.mjs b/client/webpack.dev.mjs new file mode 100644 index 000000000..5ad42ed45 --- /dev/null +++ b/client/webpack.dev.mjs @@ -0,0 +1,33 @@ +import path from 'path'; +import {merge} from 'webpack-merge'; +import Dotenv from 'dotenv-webpack'; +import common from './webpack.common.mjs'; +import {fileURLToPath} from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +export default merge(common, { + mode: 'development', + output: { + filename: '[name].js', + chunkFilename: '[id].chunk.js', + path: path.resolve(__dirname, 'dist'), + clean: true, + publicPath: '/', + }, + devtool: 'eval-source-map', + devServer: { + port: 3000, + historyApiFallback: true, + hot: true, + client: { + overlay: false, + }, + }, + plugins: [ + new Dotenv({ + path: '.env.dev', + }), + ], +}); diff --git a/client/webpack.prod.mjs b/client/webpack.prod.mjs new file mode 100644 index 000000000..1cf3bc7d1 --- /dev/null +++ b/client/webpack.prod.mjs @@ -0,0 +1,31 @@ +import path from 'path'; +import {merge} from 'webpack-merge'; +import Dotenv from 'dotenv-webpack'; +import common from './webpack.common.mjs'; +import {fileURLToPath} from 'url'; +import {sentryWebpackPlugin} from '@sentry/webpack-plugin'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +export default merge(common, { + mode: 'production', + output: { + filename: '[name].[hash].js', + chunkFilename: '[id].[hash].chunk.js', + path: path.resolve(__dirname, 'dist'), + clean: true, + publicPath: '/', + }, + devtool: 'source-map', + plugins: [ + new Dotenv({ + path: '.env.prod', + }), + sentryWebpackPlugin({ + authToken: process.env.SENTRY_AUTH_TOKEN, + org: 'wtc-o6', + project: 'javascript-react', + }), + ], +}); diff --git a/server/.gitignore b/server/.gitignore new file mode 100644 index 000000000..671ee930b --- /dev/null +++ b/server/.gitignore @@ -0,0 +1,244 @@ +# Created by https://www.toptal.com/developers/gitignore/api/java,intellij,gradle,macos,windows,linux +# Edit at https://www.toptal.com/developers/gitignore?templates=java,intellij,gradle,macos,windows,linux + +### Intellij ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Intellij Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +# https://plugins.jetbrains.com/plugin/7973-sonarlint +.idea/**/sonarlint/ + +# SonarQube Plugin +# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin +.idea/**/sonarIssues.xml + +# Markdown Navigator plugin +# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced +.idea/**/markdown-navigator.xml +.idea/**/markdown-navigator-enh.xml +.idea/**/markdown-navigator/ + +# Cache file creation bug +# See https://youtrack.jetbrains.com/issue/JBR-2257 +.idea/$CACHE_FILE$ + +# CodeStream plugin +# https://plugins.jetbrains.com/plugin/12206-codestream +.idea/codestream.xml + +# Azure Toolkit for IntelliJ plugin +# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij +.idea/**/azureSettings.xml + +### Java ### +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +### Gradle ### +.gradle +**/build/ +!src/**/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Avoid ignore Gradle wrappper properties +!gradle-wrapper.properties + +# Cache of project +.gradletasknamecache + +# Eclipse Gradle plugin generated files +# Eclipse Core +.project +# JDT-specific (Eclipse Java Development Tools) +.classpath + +### Gradle Patch ### +# Java heap dump +*.hprof + +# End of https://www.toptal.com/developers/gitignore/api/java,intellij,gradle,macos,windows,linux diff --git a/server/.gitkeep b/server/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/server/Dockerfile b/server/Dockerfile new file mode 100644 index 000000000..df2cf44e0 --- /dev/null +++ b/server/Dockerfile @@ -0,0 +1,9 @@ +FROM openjdk:17-jdk-slim + +WORKDIR /app + +COPY /build/libs/*.jar /app/haengdong-0.0.1-SNAPSHOT.jar + +EXPOSE 8080 +ENTRYPOINT ["java"] +CMD ["-Dspring.profiles.active=${SPRING_PROFILES_ACTIVE}", "-Duser.timezone=Asia/Seoul", "-jar", "haengdong-0.0.1-SNAPSHOT.jar"] diff --git a/server/build.gradle b/server/build.gradle new file mode 100644 index 000000000..4229de130 --- /dev/null +++ b/server/build.gradle @@ -0,0 +1,86 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '3.3.1' + id 'io.spring.dependency-management' version '1.1.5' + id 'org.asciidoctor.jvm.convert' version '3.3.2' +} + +group = 'server' +version = '0.0.1-SNAPSHOT' + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } +} + +configurations { + compileOnly { + extendsFrom annotationProcessor + } + asciidoctorExt +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.boot:spring-boot-starter-actuator' + + implementation 'io.jsonwebtoken:jjwt:0.9.1' + implementation 'javax.xml.bind:jaxb-api:2.3.1' + + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + + runtimeOnly 'com.h2database:h2' + runtimeOnly 'com.mysql:mysql-connector-j' + + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + + asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor' + testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' +} + +ext { + snippetsDir = file('build/generated-snippets') +} + +test { + useJUnitPlatform() + outputs.dir snippetsDir +} + +asciidoctor { + inputs.dir snippetsDir + configurations 'asciidoctorExt' + baseDirFollowsSourceFile() + dependsOn test +} + +tasks.resolveMainClassName { + dependsOn 'copyApiDocuments' +} + +tasks.register('copyApiDocuments', Copy) { + dependsOn asciidoctor + from file("build/docs/asciidoc") + into file("build/resources/main/static/docs") +} + +bootJar { + dependsOn copyApiDocuments +} + +jar { + enabled = false +} + +build { + dependsOn copyApiDocuments +} diff --git a/server/docs/24-08-04-erd.sql b/server/docs/24-08-04-erd.sql new file mode 100644 index 000000000..ae2fbc4a5 --- /dev/null +++ b/server/docs/24-08-04-erd.sql @@ -0,0 +1,65 @@ +-- Create tables +CREATE TABLE action +( + event_id BIGINT, + id BIGINT AUTO_INCREMENT, + sequence BIGINT, + PRIMARY KEY (id) +); + +CREATE TABLE bill_action +( + action_id BIGINT UNIQUE, + id BIGINT AUTO_INCREMENT, + price BIGINT, + title VARCHAR(30), + PRIMARY KEY (id) +); + +CREATE TABLE event +( + id BIGINT AUTO_INCREMENT, + name VARCHAR(255), + token VARCHAR(255), + PRIMARY KEY (id) +); + +CREATE TABLE event_step +( + event_id BIGINT, + id BIGINT AUTO_INCREMENT, + sequence BIGINT, + name VARCHAR(255), + PRIMARY KEY (id) +); + +CREATE TABLE member_action +( + action_id BIGINT UNIQUE, + id BIGINT AUTO_INCREMENT, + member_group_id BIGINT, + member_name VARCHAR(255), + status ENUM('IN', 'OUT'), + PRIMARY KEY (id) +); + +-- Add foreign key constraints +ALTER TABLE action + ADD CONSTRAINT FKgf0qmub9va1xbe44nehny31yw + FOREIGN KEY (event_id) + REFERENCES event (id); + +ALTER TABLE bill_action + ADD CONSTRAINT FK54tx517tp0ry6453olkply4us + FOREIGN KEY (action_id) + REFERENCES action (id); + +ALTER TABLE event_step + ADD CONSTRAINT FKe3rkib91cvl0x5w9wqkshmn81 + FOREIGN KEY (event_id) + REFERENCES event (id); + +ALTER TABLE member_action + ADD CONSTRAINT FK5jna51dn8fs2ir52l4uwn517u + FOREIGN KEY (action_id) + REFERENCES action (id); diff --git a/server/docs/24-08-04-erd.svg b/server/docs/24-08-04-erd.svg new file mode 100644 index 000000000..5a4bac225 --- /dev/null +++ b/server/docs/24-08-04-erd.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Do not edit this file with editors other than draw.io --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1993px" height="1581px" viewBox="-0.5 -0.5 1993 1581" content="<mxfile host="app.diagrams.net" modified="2024-07-25T04:17:06.208Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" etag="gR5VLfYLO6MRu5dHcV28" version="24.7.3" type="github"> <diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1"> <mxGraphModel dx="2380" dy="2150" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0"> <root> <mxCell id="WIyWlLk6GJQsqaUBKTNV-0" /> <mxCell id="WIyWlLk6GJQsqaUBKTNV-1" parent="WIyWlLk6GJQsqaUBKTNV-0" /> <mxCell id="8gZzuRhjrYuwNxX9kY4q-98" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="-442" y="-590" width="1992" height="1580" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-47" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;startArrow=ERone;startFill=0;endArrow=ERzeroToMany;endFill=0;dashed=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="8gZzuRhjrYuwNxX9kY4q-0" target="8gZzuRhjrYuwNxX9kY4q-37" edge="1"> <mxGeometry relative="1" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-66" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;startArrow=ERone;startFill=0;endArrow=ERzeroToMany;endFill=0;dashed=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="8gZzuRhjrYuwNxX9kY4q-0" target="8gZzuRhjrYuwNxX9kY4q-56" edge="1"> <mxGeometry relative="1" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-0" value="Event" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="40" y="40" width="280" height="120" as="geometry"> <mxRectangle x="480" y="530" width="70" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-1" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="8gZzuRhjrYuwNxX9kY4q-0" vertex="1"> <mxGeometry y="30" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-2" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-1" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-3" value="event_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-1" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-137" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-1" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-7" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-0" vertex="1"> <mxGeometry y="60" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-8" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-7" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-9" value="token" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-7" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-138" value="varchar(20)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-7" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-4" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-0" vertex="1"> <mxGeometry y="90" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-5" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-4" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-6" value="name" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-4" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-139" value="varchar(255)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-4" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-37" value="Event_Step" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="40" y="240" width="280" height="150" as="geometry"> <mxRectangle x="480" y="530" width="70" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-38" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="8gZzuRhjrYuwNxX9kY4q-37" vertex="1"> <mxGeometry y="30" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-39" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-38" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-40" value="event_step_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-38" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-143" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-38" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-41" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-37" vertex="1"> <mxGeometry y="60" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-42" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-41" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-43" value="name" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-41" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-144" value="varchar(30)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-41" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-44" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-37" vertex="1"> <mxGeometry y="90" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-45" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-44" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-46" value="sequence" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-44" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-145" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-44" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-48" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-37" vertex="1"> <mxGeometry y="120" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-49" value="FK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-48" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-50" value="event_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-48" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-146" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-48" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-77" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;dashed=1;startArrow=ERone;startFill=0;endArrow=ERone;endFill=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="8gZzuRhjrYuwNxX9kY4q-56" target="8gZzuRhjrYuwNxX9kY4q-67" edge="1"> <mxGeometry relative="1" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-91" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;dashed=1;startArrow=ERone;startFill=0;endArrow=ERone;endFill=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="8gZzuRhjrYuwNxX9kY4q-56" target="8gZzuRhjrYuwNxX9kY4q-81" edge="1"> <mxGeometry relative="1" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-56" value="Action" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="414" y="40" width="280" height="120" as="geometry"> <mxRectangle x="480" y="530" width="70" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-57" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="8gZzuRhjrYuwNxX9kY4q-56" vertex="1"> <mxGeometry y="30" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-58" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-57" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-59" value="action_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-57" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-140" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-57" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-60" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-56" vertex="1"> <mxGeometry y="60" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-61" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-60" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-62" value="sequence" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-60" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-141" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-60" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-63" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-56" vertex="1"> <mxGeometry y="90" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-64" value="FK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-63" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-65" value="event_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-63" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-142" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-63" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-67" value="Bill_Action" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="414" y="240" width="280" height="150" as="geometry"> <mxRectangle x="480" y="530" width="70" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-68" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="8gZzuRhjrYuwNxX9kY4q-67" vertex="1"> <mxGeometry y="30" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-69" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-68" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-70" value="bill_action_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-68" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-147" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-68" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-71" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-67" vertex="1"> <mxGeometry y="60" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-72" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-71" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-73" value="title" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-71" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-148" value="varchar(30)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-71" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-78" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-67" vertex="1"> <mxGeometry y="90" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-79" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-78" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-80" value="price" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-78" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-149" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-78" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-74" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-67" vertex="1"> <mxGeometry y="120" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-75" value="FK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-74" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-76" value="action_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-74" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-150" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-74" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-81" value="Member_Action" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="790" y="40" width="280" height="180" as="geometry"> <mxRectangle x="480" y="530" width="70" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-82" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="8gZzuRhjrYuwNxX9kY4q-81" vertex="1"> <mxGeometry y="30" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-83" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-82" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-84" value="member_action_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-82" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-151" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-82" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-85" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-81" vertex="1"> <mxGeometry y="60" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-86" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-85" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-87" value="member_name" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-85" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-152" value="varchar(20)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-85" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-92" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-81" vertex="1"> <mxGeometry y="90" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-93" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-92" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-94" value="status" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-92" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-153" value="varchar(10)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-92" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-95" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-81" vertex="1"> <mxGeometry y="120" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-96" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-95" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-97" value="member_group_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-95" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-154" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-95" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-88" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-81" vertex="1"> <mxGeometry y="150" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-89" value="FK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-88" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-90" value="action_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-88" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-155" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-88" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> </root> </mxGraphModel> </diagram> </mxfile> " resource="https://app.diagrams.net/?src=about#Hkunsanglee%2Fcafekiosk-study%2Fmain%2Fsrc%2Fmain%2Fresources%2Fexample2.svg#%7B%22pageId%22%3A%22C5RBs43oDa-KdzZeNtuy%22%7D"><defs/><g><g data-cell-id="WIyWlLk6GJQsqaUBKTNV-0"><g data-cell-id="WIyWlLk6GJQsqaUBKTNV-1"><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-98"><g><rect x="0" y="0" width="1992" height="1580" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-47"><g><path d="M 622 750 L 622 814.5" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 626 754 L 618 754" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><ellipse cx="622" cy="818" rx="3" ry="3" fill="none" stroke="rgb(0, 0, 0)" pointer-events="all"/><path d="M 626 830 L 622 822 L 618 830 M 622 822 L 622 830" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-66"><g><path d="M 762 690 L 840.5 690" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 766 686 L 766 694" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><ellipse cx="844" cy="690" rx="3" ry="3" fill="none" stroke="rgb(0, 0, 0)" pointer-events="all"/><path d="M 856 686 L 848 690 L 856 694 M 848 690 L 856 690" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-0"><g><path d="M 482 660 L 482 630 L 762 630 L 762 660" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 482 660 L 482 750 L 762 750 L 762 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 482 660 L 762 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 512 660 L 512 690 L 512 720 L 512 750" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 632 660 L 632 690 L 632 720 L 632 750" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 645px; margin-left: 622px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Event</div></div></div></foreignObject><text x="622" y="649" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">Event</text></switch></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-1"><g><path d="M 482 660 M 762 660 M 762 690 L 482 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="none"/></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-2"><g><rect x="482" y="660" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 660 M 512 660 M 512 690 M 482 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 675px; margin-left: 483px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">PK</div></div></div></foreignObject><text x="497" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">PK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-3"><g><rect x="512" y="660" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 660 M 632 660 M 632 690 M 512 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 675px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">event_id</div></div></div></foreignObject><text x="520" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">event_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-137"><g><rect x="632" y="660" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 660 M 762 660 M 762 690 M 632 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 675px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="640" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-7"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-8"><g><rect x="482" y="690" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 690 M 512 690 M 512 720 M 482 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-9"><g><rect x="512" y="690" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 690 M 632 690 M 632 720 M 512 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 705px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">token</div></div></div></foreignObject><text x="520" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">token</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-138"><g><rect x="632" y="690" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 690 M 762 690 M 762 720 M 632 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 705px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(20)</div></div></div></foreignObject><text x="640" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(20)</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-4"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-5"><g><rect x="482" y="720" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 720 M 512 720 M 512 750 M 482 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-6"><g><rect x="512" y="720" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 720 M 632 720 M 632 750 M 512 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 735px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">name</div></div></div></foreignObject><text x="520" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">name</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-139"><g><rect x="632" y="720" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 720 M 762 720 M 762 750 M 632 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 735px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(255)</div></div></div></foreignObject><text x="640" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(255)</text></switch></g></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-37"><g><path d="M 482 860 L 482 830 L 762 830 L 762 860" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 482 860 L 482 980 L 762 980 L 762 860" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 482 860 L 762 860" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 512 860 L 512 890 L 512 920 L 512 950 L 512 980" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 632 860 L 632 890 L 632 920 L 632 950 L 632 980" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 845px; margin-left: 622px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Event_Step</div></div></div></foreignObject><text x="622" y="849" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">Event_Step</text></switch></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-38"><g><path d="M 482 860 M 762 860 M 762 890 L 482 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="none"/></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-39"><g><rect x="482" y="860" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 860 M 512 860 M 512 890 M 482 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 875px; margin-left: 483px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">PK</div></div></div></foreignObject><text x="497" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">PK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-40"><g><rect x="512" y="860" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 860 M 632 860 M 632 890 M 512 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 875px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">event_step_id</div></div></div></foreignObject><text x="520" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">event_step_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-143"><g><rect x="632" y="860" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 860 M 762 860 M 762 890 M 632 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 875px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="640" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-41"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-42"><g><rect x="482" y="890" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 890 M 512 890 M 512 920 M 482 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-43"><g><rect x="512" y="890" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 890 M 632 890 M 632 920 M 512 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 905px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">name</div></div></div></foreignObject><text x="520" y="909" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">name</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-144"><g><rect x="632" y="890" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 890 M 762 890 M 762 920 M 632 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 905px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(30)</div></div></div></foreignObject><text x="640" y="909" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(30)</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-44"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-45"><g><rect x="482" y="920" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 920 M 512 920 M 512 950 M 482 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-46"><g><rect x="512" y="920" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 920 M 632 920 M 632 950 M 512 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 935px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">sequence</div></div></div></foreignObject><text x="520" y="939" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">sequence</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-145"><g><rect x="632" y="920" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 920 M 762 920 M 762 950 M 632 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 935px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="640" y="939" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-48"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-49"><g><rect x="482" y="950" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 950 M 512 950 M 512 980 M 482 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 965px; margin-left: 483px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">FK</div></div></div></foreignObject><text x="497" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle">FK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-50"><g><rect x="512" y="950" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 950 M 632 950 M 632 980 M 512 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 965px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">event_id</div></div></div></foreignObject><text x="520" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">event_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-146"><g><rect x="632" y="950" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 950 M 762 950 M 762 980 M 632 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 965px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="640" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-77"><g><path d="M 996 750 L 996 830" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 1000 754 L 992 754" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 992 826 L 1000 826" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-91"><g><path d="M 1136 690 L 1184 690 L 1184 720 L 1232 720" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 1140 686 L 1140 694" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 1228 724 L 1228 716" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-56"><g><path d="M 856 660 L 856 630 L 1136 630 L 1136 660" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 856 660 L 856 750 L 1136 750 L 1136 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 856 660 L 1136 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 886 660 L 886 690 L 886 720 L 886 750" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 1006 660 L 1006 690 L 1006 720 L 1006 750" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 645px; margin-left: 996px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Action</div></div></div></foreignObject><text x="996" y="649" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">Action</text></switch></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-57"><g><path d="M 856 660 M 1136 660 M 1136 690 L 856 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="none"/></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-58"><g><rect x="856" y="660" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 660 M 886 660 M 886 690 M 856 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 675px; margin-left: 857px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">PK</div></div></div></foreignObject><text x="871" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">PK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-59"><g><rect x="886" y="660" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 660 M 1006 660 M 1006 690 M 886 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 675px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">action_id</div></div></div></foreignObject><text x="894" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">action_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-140"><g><rect x="1006" y="660" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 660 M 1136 660 M 1136 690 M 1006 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 675px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-60"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-61"><g><rect x="856" y="690" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 690 M 886 690 M 886 720 M 856 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-62"><g><rect x="886" y="690" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 690 M 1006 690 M 1006 720 M 886 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 705px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">sequence</div></div></div></foreignObject><text x="894" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">sequence</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-141"><g><rect x="1006" y="690" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 690 M 1136 690 M 1136 720 M 1006 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 705px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-63"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-64"><g><rect x="856" y="720" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 720 M 886 720 M 886 750 M 856 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 735px; margin-left: 857px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">FK</div></div></div></foreignObject><text x="871" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle">FK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-65"><g><rect x="886" y="720" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 720 M 1006 720 M 1006 750 M 886 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 735px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">event_id</div></div></div></foreignObject><text x="894" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">event_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-142"><g><rect x="1006" y="720" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 720 M 1136 720 M 1136 750 M 1006 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 735px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-67"><g><path d="M 856 860 L 856 830 L 1136 830 L 1136 860" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 856 860 L 856 980 L 1136 980 L 1136 860" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 856 860 L 1136 860" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 886 860 L 886 890 L 886 920 L 886 950 L 886 980" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 1006 860 L 1006 890 L 1006 920 L 1006 950 L 1006 980" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 845px; margin-left: 996px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Bill_Action</div></div></div></foreignObject><text x="996" y="849" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">Bill_Action</text></switch></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-68"><g><path d="M 856 860 M 1136 860 M 1136 890 L 856 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="none"/></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-69"><g><rect x="856" y="860" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 860 M 886 860 M 886 890 M 856 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 875px; margin-left: 857px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">PK</div></div></div></foreignObject><text x="871" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">PK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-70"><g><rect x="886" y="860" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 860 M 1006 860 M 1006 890 M 886 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 875px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bill_action_id</div></div></div></foreignObject><text x="894" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bill_action_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-147"><g><rect x="1006" y="860" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 860 M 1136 860 M 1136 890 M 1006 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 875px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-71"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-72"><g><rect x="856" y="890" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 890 M 886 890 M 886 920 M 856 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-73"><g><rect x="886" y="890" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 890 M 1006 890 M 1006 920 M 886 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 905px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">title</div></div></div></foreignObject><text x="894" y="909" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">title</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-148"><g><rect x="1006" y="890" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 890 M 1136 890 M 1136 920 M 1006 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 905px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(30)</div></div></div></foreignObject><text x="1014" y="909" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(30)</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-78"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-79"><g><rect x="856" y="920" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 920 M 886 920 M 886 950 M 856 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-80"><g><rect x="886" y="920" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 920 M 1006 920 M 1006 950 M 886 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 935px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">price</div></div></div></foreignObject><text x="894" y="939" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">price</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-149"><g><rect x="1006" y="920" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 920 M 1136 920 M 1136 950 M 1006 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 935px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="939" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-74"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-75"><g><rect x="856" y="950" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 950 M 886 950 M 886 980 M 856 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 965px; margin-left: 857px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">FK</div></div></div></foreignObject><text x="871" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle">FK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-76"><g><rect x="886" y="950" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 950 M 1006 950 M 1006 980 M 886 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 965px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">action_id</div></div></div></foreignObject><text x="894" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">action_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-150"><g><rect x="1006" y="950" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 950 M 1136 950 M 1136 980 M 1006 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 965px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-81"><g><path d="M 1232 660 L 1232 630 L 1512 630 L 1512 660" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 1232 660 L 1232 810 L 1512 810 L 1512 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 1232 660 L 1512 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 1262 660 L 1262 690 L 1262 720 L 1262 750 L 1262 780 L 1262 810" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 1382 660 L 1382 690 L 1382 720 L 1382 750 L 1382 780 L 1382 810" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 645px; margin-left: 1372px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Member_Action</div></div></div></foreignObject><text x="1372" y="649" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">Member_Action</text></switch></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-82"><g><path d="M 1232 660 M 1512 660 M 1512 690 L 1232 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="none"/></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-83"><g><rect x="1232" y="660" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1232 660 M 1262 660 M 1262 690 M 1232 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 675px; margin-left: 1233px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">PK</div></div></div></foreignObject><text x="1247" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">PK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-84"><g><rect x="1262" y="660" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1262 660 M 1382 660 M 1382 690 M 1262 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 675px; margin-left: 1270px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">member_action_id</div></div></div></foreignObject><text x="1270" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">member_action_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-151"><g><rect x="1382" y="660" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1382 660 M 1512 660 M 1512 690 M 1382 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 675px; margin-left: 1390px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1390" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-85"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-86"><g><rect x="1232" y="690" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1232 690 M 1262 690 M 1262 720 M 1232 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-87"><g><rect x="1262" y="690" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1262 690 M 1382 690 M 1382 720 M 1262 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 705px; margin-left: 1270px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">member_name</div></div></div></foreignObject><text x="1270" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">member_name</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-152"><g><rect x="1382" y="690" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1382 690 M 1512 690 M 1512 720 M 1382 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 705px; margin-left: 1390px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(20)</div></div></div></foreignObject><text x="1390" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(20)</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-92"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-93"><g><rect x="1232" y="720" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1232 720 M 1262 720 M 1262 750 M 1232 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-94"><g><rect x="1262" y="720" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1262 720 M 1382 720 M 1382 750 M 1262 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 735px; margin-left: 1270px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">status</div></div></div></foreignObject><text x="1270" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">status</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-153"><g><rect x="1382" y="720" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1382 720 M 1512 720 M 1512 750 M 1382 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 735px; margin-left: 1390px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(10)</div></div></div></foreignObject><text x="1390" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(10)</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-95"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-96"><g><rect x="1232" y="750" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1232 750 M 1262 750 M 1262 780 M 1232 780" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-97"><g><rect x="1262" y="750" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1262 750 M 1382 750 M 1382 780 M 1262 780" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 765px; margin-left: 1270px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">member_group_id</div></div></div></foreignObject><text x="1270" y="769" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">member_group_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-154"><g><rect x="1382" y="750" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1382 750 M 1512 750 M 1512 780 M 1382 780" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 765px; margin-left: 1390px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1390" y="769" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-88"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-89"><g><rect x="1232" y="780" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1232 780 M 1262 780 M 1262 810 M 1232 810" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 795px; margin-left: 1233px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">FK</div></div></div></foreignObject><text x="1247" y="799" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle">FK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-90"><g><rect x="1262" y="780" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1262 780 M 1382 780 M 1382 810 M 1262 810" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 795px; margin-left: 1270px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">action_id</div></div></div></foreignObject><text x="1270" y="799" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">action_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-155"><g><rect x="1382" y="780" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1382 780 M 1512 780 M 1512 810 M 1382 810" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 795px; margin-left: 1390px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1390" y="799" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g></g></g></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.drawio.com/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> \ No newline at end of file diff --git a/server/gradle/wrapper/gradle-wrapper.jar b/server/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..e6441136f Binary files /dev/null and b/server/gradle/wrapper/gradle-wrapper.jar differ diff --git a/server/gradle/wrapper/gradle-wrapper.properties b/server/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..a4413138c --- /dev/null +++ b/server/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/server/gradlew b/server/gradlew new file mode 100644 index 000000000..b740cf133 --- /dev/null +++ b/server/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright ยฉ 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions ยซ$varยป, ยซ${var}ยป, ยซ${var:-default}ยป, ยซ${var+SET}ยป, +# ยซ${var#prefix}ยป, ยซ${var%suffix}ยป, and ยซ$( cmd )ยป; +# * compound commands having a testable exit status, especially ยซcaseยป; +# * various built-in commands including ยซcommandยป, ยซsetยป, and ยซulimitยป. +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/server/gradlew.bat b/server/gradlew.bat new file mode 100644 index 000000000..25da30dbd --- /dev/null +++ b/server/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/server/settings.gradle b/server/settings.gradle new file mode 100644 index 000000000..dbbee46fb --- /dev/null +++ b/server/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'haengdong' diff --git a/server/src/docs/asciidoc/billAction.adoc b/server/src/docs/asciidoc/billAction.adoc new file mode 100644 index 000000000..dfd7e26db --- /dev/null +++ b/server/src/docs/asciidoc/billAction.adoc @@ -0,0 +1,121 @@ +== ์ง€์ถœ ์•ก์…˜ + +=== ์ง€์ถœ ์•ก์…˜ ์ƒ์„ฑ + +operation::createBillActions[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"REQUEST_EMPTY", + "message":"์ง€์ถœ ๊ธˆ์•ก์€ ๋น„์–ด ์žˆ์œผ๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค." + }, + { + "code":"REQUEST_EMPTY", + "message":"์ง€์ถœ ๋‚ด์—ญ์€ ๋น„์–ด ์žˆ์œผ๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค." + }, + { + "code":"BILL_ACTION_TITLE_INVALID", + "message":"์•ž๋’ค ๊ณต๋ฐฑ์„ ์ œ๊ฑฐํ•œ ์ง€์ถœ ๋‚ด์—ญ ์ œ๋ชฉ์€ %d ~ %d์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค." + }, + { + "code":"BILL_ACTION_PRICE_INVALID", + "message":"์ง€์ถœ ๊ธˆ์•ก์€ 10,000,000 ์ดํ•˜์˜ ์ž์—ฐ์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค." + }, + { + "code":"EVENT_NOT_FOUND", + "message":"์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค." + }, + { + "code":"TOKEN_NOT_FOUND", + "message":"ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค." + }, + { + "code":"TOKEN_EXPIRED", + "message":"ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค." + }, + { + "code":"TOKEN_INVALID", + "message":"์œ ํšจํ•˜์ง€ ์•Š์€ ํ† ํฐ์ž…๋‹ˆ๋‹ค." + } +] +---- + +=== ์ง€์ถœ ์•ก์…˜ ์ˆ˜์ • + +operation::updateBillAction[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"REQUEST_EMPTY", + "message":"์ง€์ถœ ๋‚ด์—ญ ์ œ๋ชฉ์€ ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค." + }, + { + "code":"REQUEST_EMPTY", + "message":"์ง€์ถœ ๊ธˆ์•ก์€ ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค." + }, + { + "code":"BILL_ACTION_TITLE_INVALID", + "message":"์•ž๋’ค ๊ณต๋ฐฑ์„ ์ œ๊ฑฐํ•œ ์ง€์ถœ ๋‚ด์—ญ ์ œ๋ชฉ์€ %d ~ %d์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค." + }, + { + "code":"BILL_ACTION_PRICE_INVALID", + "message":"์ง€์ถœ ๊ธˆ์•ก์€ %,d ์ดํ•˜์˜ ์ž์—ฐ์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค." + }, + { + "code":"EVENT_NOT_FOUND", + "message":"์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค." + }, + { + "code":"BILL_ACTION_NOT_FOUND", + "message":"์กด์žฌํ•˜์ง€ ์•Š๋Š” ์ง€์ถœ ์•ก์…˜์ž…๋‹ˆ๋‹ค." + }, + { + "code":"TOKEN_NOT_FOUND", + "message":"ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค." + }, + { + "code":"TOKEN_EXPIRED", + "message":"ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค." + }, + { + "code":"TOKEN_INVALID", + "message":"์œ ํšจํ•˜์ง€ ์•Š์€ ํ† ํฐ์ž…๋‹ˆ๋‹ค." + } +] +---- + +=== ์ง€์ถœ ์•ก์…˜ ์‚ญ์ œ + +operation::deleteBillAction[snippets="path-parameters,http-request,http-response,request-cookies"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"EVENT_NOT_FOUND", + "message":"์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค." + }, + { + "code":"TOKEN_NOT_FOUND", + "message":"ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค." + }, + { + "code":"TOKEN_EXPIRED", + "message":"ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค." + }, + { + "code":"TOKEN_INVALID", + "message":"์œ ํšจํ•˜์ง€ ์•Š์€ ํ† ํฐ์ž…๋‹ˆ๋‹ค." + } +] +---- diff --git a/server/src/docs/asciidoc/billActionDetail.adoc b/server/src/docs/asciidoc/billActionDetail.adoc new file mode 100644 index 000000000..a8f19f21b --- /dev/null +++ b/server/src/docs/asciidoc/billActionDetail.adoc @@ -0,0 +1,93 @@ +== ์ง€์ถœ ์ƒ์„ธ + +=== ์ง€์ถœ ์ƒ์„ธ ์กฐํšŒ + +operation::findBillActionDetailsTest[snippets="path-parameters,http-request,http-response,request-cookies"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code": "EVENT_NOT_FOUND", + "message": "์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค." + }, + { + "code": "BILL_ACTION_NOT_FOUND", + "message": "์กด์žฌํ•˜์ง€ ์•Š๋Š” ์ง€์ถœ ์•ก์…˜์ž…๋‹ˆ๋‹ค." + }, + { + "code": "BILL_ACTION_DETAIL_NOT_FOUND", + "message": "์กด์žฌํ•˜์ง€ ์•Š๋Š” ์ฐธ์—ฌ์ž ์ง€์ถœ์ž…๋‹ˆ๋‹ค." + }, + { + "code": "TOKEN_NOT_FOUND", + "message": "ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค." + }, + { + "code": "TOKEN_EXPIRED", + "message": "๋งŒ๋ฃŒ๋œ ํ† ํฐ์ž…๋‹ˆ๋‹ค." + }, + { + "code": "TOKEN_INVALID", + "message": "์œ ํšจํ•˜์ง€ ์•Š์€ ํ† ํฐ์ž…๋‹ˆ๋‹ค." + }, + { + "code": "FORBIDDEN", + "message": "์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค." + } +] +---- + +=== ์ง€์ถœ ์ƒ์„ธ ์ˆ˜์ • + +operation::updateBillActionDetailsTest[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code": "REQUEST_EMPTY", + "message": "๋ฉค๋ฒ„ ์ด๋ฆ„์€ ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค." + }, + { + "code": "REQUEST_EMPTY", + "message": "์ง€์ถœ ๊ธˆ์•ก์€ ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค." + }, + { + "code": "EVENT_NOT_FOUND", + "message": "์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค." + }, + { + "code": "BILL_ACTION_NOT_FOUND", + "message": "์กด์žฌํ•˜์ง€ ์•Š๋Š” ์ง€์ถœ ์•ก์…˜์ž…๋‹ˆ๋‹ค." + }, + { + "code": "BILL_ACTION_DETAIL_NOT_FOUND", + "message": "์กด์žฌํ•˜์ง€ ์•Š๋Š” ์ฐธ์—ฌ์ž ์ง€์ถœ์ž…๋‹ˆ๋‹ค." + }, + { + "code": "BILL_ACTION_PRICE_NOT_MATCHED", + "message": "์ง€์ถœ ์ด์•ก์ด ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค." + }, + { + "code": "TOKEN_NOT_FOUND", + "message": "ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค." + }, + { + "code": "TOKEN_EXPIRED", + "message": "๋งŒ๋ฃŒ๋œ ํ† ํฐ์ž…๋‹ˆ๋‹ค." + }, + { + "code": "TOKEN_INVALID", + "message": "์œ ํšจํ•˜์ง€ ์•Š์€ ํ† ํฐ์ž…๋‹ˆ๋‹ค." + }, + { + "code": "FORBIDDEN", + "message": "์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค." + } +] +---- diff --git a/server/src/docs/asciidoc/event.adoc b/server/src/docs/asciidoc/event.adoc new file mode 100644 index 000000000..72511b91b --- /dev/null +++ b/server/src/docs/asciidoc/event.adoc @@ -0,0 +1,205 @@ +== ํ–‰์‚ฌ + +=== ํ–‰์‚ฌ ์ƒ์„ฑ + +operation::createEvent[snippets="http-request,request-body,request-fields,response-body,response-fields,http-response,response-cookies"] +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"REQUEST_EMPTY", + "message":"ํ–‰์‚ฌ ์ด๋ฆ„์€ ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค." + }, + { + "code":"EVENT_NAME_LENGTH_INVALID", + "message":"ํ–‰์‚ฌ ์ด๋ฆ„์€ 2์ž ์ด์ƒ 30์ž ์ดํ•˜๋งŒ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ž…๋ ฅํ•œ ์ด๋ฆ„ ๊ธธ์ด : 21" + }, + { + "code":"EVENT_NAME_MULTIPLE_BLANK", + "message":"ํ–‰์‚ฌ ์ด๋ฆ„์—๋Š” ๊ณต๋ฐฑ ๋ฌธ์ž๊ฐ€ ์—ฐ์†๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ž…๋ ฅํ•œ ์ด๋ฆ„ : ๊ณต๋ฐฑ ๋ฌธ์ž" + }, + { + "code":"EVENT_PASSWORD_INVALID", + "message":"๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” 4์ž๋ฆฌ ์ˆซ์ž๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค." + } +] +---- + +=== ํ–‰์‚ฌ ๊ด€๋ฆฌ์ž ๋กœ๊ทธ์ธ + +operation::eventLogin[snippets="path-parameters,http-request,request-body,request-fields,http-response,response-cookies"] +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"EVENT_NOT_FOUND", + "message":"์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค." + }, + { + "code":"REQUEST_EMPTY", + "message":"๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค." + }, + { + "code":"PASSWORD_INVALID", + "message":"๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค." + } +] +---- + +=== ํ–‰์‚ฌ ์ •๋ณด ์กฐํšŒ + +operation::getEvent[snippets="path-parameters,http-request,response-body,response-fields,http-response"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"EVENT_NOT_FOUND", + "message":"์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค." + } +] +---- + +=== ํ–‰์‚ฌ ์ „์ฒด ์ฐธ์—ฌ์ž ๋ชฉ๋ก ์กฐํšŒ + +operation::findAllEventMember[snippets="path-parameters,http-request,response-body,response-fields,http-response,response-fields"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"EVENT_NOT_FOUND", + "message":"์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค." + } +] +---- + +=== ํ–‰์‚ฌ ์ „์ฒด ์•ก์…˜ ์ด๋ ฅ ์กฐํšŒ + +operation::findActions[snippets="path-parameters,http-request,http-response,response-fields"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"EVENT_NOT_FOUND", + "message":"์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค." + } +] +---- + +=== ํ–‰์‚ฌ ์ฐธ์—ฌ์ž ์ด๋ฆ„ ๋ณ€๊ฒฝ + +operation::updateEventMemberName[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"] +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + + { + "code":"MEMBER_NAME_CHANGE_DUPLICATE", + "message":"์ค‘๋ณต๋œ ์ฐธ์—ฌ ์ธ์› ์ด๋ฆ„ ๋ณ€๊ฒฝ ์š”์ฒญ์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค." + }, + { + "code":"MEMBER_NOT_EXIST", + "message":"ํ˜„์žฌ ์ฐธ์—ฌํ•˜๊ณ  ์žˆ์ง€ ์•Š๋Š” ์ธ์›์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค." + }, + { + "code":"REQUEST_EMPTY", + "message":"๋ฉค๋ฒ„ ์ด๋ฆ„์€ ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค." + }, + { + "code":"MEMBER_NAME_LENGTH_INVALID", + "message":"๋ฉค๋ฒ„ ์ด๋ฆ„์€ 1์ž ์ด์ƒ 4์ž ์ดํ•˜๋งŒ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค." + }, + { + "code":"EVENT_NOT_FOUND", + "message":"์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค." + }, + { + "code":"MEMBER_NAME_DUPLICATE", + "message":"์ค‘๋ณต๋œ ํ–‰์‚ฌ ์ฐธ์—ฌ ์ธ์› ์ด๋ฆ„์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค." + }, + { + "code":"TOKEN_NOT_FOUND", + "message":"ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค." + }, + { + "code":"TOKEN_EXPIRED", + "message":"๋งŒ๋ฃŒ๋œ ํ† ํฐ์ž…๋‹ˆ๋‹ค." + }, + { + "code":"TOKEN_INVALID", + "message":"์œ ํšจํ•˜์ง€ ์•Š์€ ํ† ํฐ์ž…๋‹ˆ๋‹ค." + } +] +---- + +=== ํ–‰์‚ฌ ์ฐธ์—ฌ์ž ์‚ญ์ œ (ํŠน์ • ์ฐธ์—ฌ์ž์˜ ๋ชจ๋“  ์ฐธ์—ฌ์ž ์•ก์…˜ ์‚ญ์ œ) + +operation::deleteAllMemberActionByName[snippets="path-parameters,http-request,http-response,request-cookies"] +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"EVENT_NOT_FOUND", + "message":"์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค." + }, + { + "code":"TOKEN_NOT_FOUND", + "message":"ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค." + }, + { + "code":"TOKEN_EXPIRED", + "message":"ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค." + }, + { + "code":"TOKEN_INVALID", + "message":"์œ ํšจํ•˜์ง€ ์•Š์€ ํ† ํฐ์ž…๋‹ˆ๋‹ค." + } +] +---- + +=== ํ–‰์‚ฌ ์–ด๋“œ๋ฏผ ๊ถŒํ•œ ํ™•์ธ + +operation::authenticateEvent[snippets="http-request,http-response,request-cookies"] +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code": "EVENT_NOT_FOUND", + "message": "์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค." + }, + { + "code": "TOKEN_NOT_FOUND", + "message": "ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค." + }, + { + "code": "TOKEN_EXPIRED", + "message": "๋งŒ๋ฃŒ๋œ ํ† ํฐ์ž…๋‹ˆ๋‹ค." + }, + { + "code": "TOKEN_INVALID", + "message": "์œ ํšจํ•˜์ง€ ์•Š์€ ํ† ํฐ์ž…๋‹ˆ๋‹ค." + }, + { + "code": "FORBIDDEN", + "message": "์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค." + } +] +---- diff --git a/server/src/docs/asciidoc/index.adoc b/server/src/docs/asciidoc/index.adoc new file mode 100644 index 000000000..8e1bcd2d0 --- /dev/null +++ b/server/src/docs/asciidoc/index.adoc @@ -0,0 +1,15 @@ +ifndef::snippets[] +:snippets: ../../build/generated-snippets +endif::[] += ํ–‰๋™๋Œ€์žฅ +:source-highlighter: highlightjs :hardbreaks: +:toc: left :doctype: book :icons: font :toc-title: ์ „์ฒด API ๋ชฉ๋ก :toclevels: 2 :sectlinks: +:sectnums: +:sectnumlevels: 2 + + +include::{docdir}/event.adoc[] +include::{docdir}/memberBillReport.adoc[] +include::{docdir}/memberAction.adoc[] +include::{docdir}/billAction.adoc[] +include::{docdir}/billActionDetail.adoc[] diff --git a/server/src/docs/asciidoc/memberAction.adoc b/server/src/docs/asciidoc/memberAction.adoc new file mode 100644 index 000000000..897102c8d --- /dev/null +++ b/server/src/docs/asciidoc/memberAction.adoc @@ -0,0 +1,100 @@ +== ์ฐธ์—ฌ์ž ์•ก์…˜ + +=== ์ฐธ์—ฌ์ž ์•ก์…˜ ์ƒ์„ฑ + +operation::createMemberAction[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"REQUEST_EMPTY", + "message":"๋ฉค๋ฒ„ ์•ก์…˜์€ ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค." + }, + { + "code":"EVENT_NOT_FOUND", + "message":"์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค." + }, + { + "code":"MEMBER_ACTION_STATUS_INVALID", + "message":"๋ฉค๋ฒ„ ์•ก์…˜์€ IN, OUT๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ž…๋ ฅํ•œ ๋ฉค๋ฒ„ ์•ก์…˜: I_N" + }, + { + "code":"MEMBER_ALREADY_EXIST", + "message":"ํ˜„์žฌ ์ฐธ์—ฌํ•˜๊ณ  ์žˆ๋Š” ์ธ์›์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค." + }, + { + "code":"MEMBER_NOT_EXIST", + "message":"ํ˜„์žฌ ์ฐธ์—ฌํ•˜๊ณ  ์žˆ์ง€ ์•Š๋Š” ์ธ์›์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค." + }, + { + "code":"MEMBER_NAME_DUPLICATE", + "message":"์ค‘๋ณต๋œ ์ด๋ฆ„์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์ž…๋ ฅ๋œ ์ด๋ฆ„: ์ด์ƒ, ์ด์ƒ, ๊ฐ์ž, ๋ฐฑํ˜ธ" + }, + { + "code":"TOKEN_NOT_FOUND", + "message":"ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค." + }, + { + "code":"TOKEN_EXPIRED", + "message":"ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค." + }, + { + "code":"TOKEN_INVALID", + "message":"์œ ํšจํ•˜์ง€ ์•Š์€ ํ† ํฐ์ž…๋‹ˆ๋‹ค." + } +] +---- + +=== ํ˜„์žฌ ํ–‰์‚ฌ์— ์ฐธ์—ฌ ์ค‘์ธ (ํƒˆ์ฃผ ๊ฐ€๋Šฅํ•œ) ์ฐธ์—ฌ์ž ๋ชฉ๋ก ์กฐํšŒ + +operation::getCurrentMembers[snippets="path-parameters,http-request,http-response,response-fields"] +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"EVENT_NOT_FOUND", + "message":"์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค." + } +] +---- + +=== ์ฐธ์—ฌ์ž ์•ก์…˜ ์‚ญ์ œ + +operation::deleteMemberAction[snippets="path-parameters,http-request,http-response,request-cookies"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"EVENT_NOT_FOUND", + "message":"์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค." + }, + { + "code":"ACTION_NOT_FOUND", + "message":"์กด์žฌํ•˜์ง€ ์•Š๋Š” ์•ก์…˜์ž…๋‹ˆ๋‹ค." + }, + { + "code":"MEMBER_ACTION_NOT_FOUND", + "message":"์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ฉค๋ฒ„ ์•ก์…˜์ž…๋‹ˆ๋‹ค." + }, + { + "code":"TOKEN_NOT_FOUND", + "message":"ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค." + }, + { + "code":"TOKEN_EXPIRED", + "message":"ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค." + }, + { + "code":"TOKEN_INVALID", + "message":"์œ ํšจํ•˜์ง€ ์•Š์€ ํ† ํฐ์ž…๋‹ˆ๋‹ค." + } +] +---- diff --git a/server/src/docs/asciidoc/memberBillReport.adoc b/server/src/docs/asciidoc/memberBillReport.adoc new file mode 100644 index 000000000..18bd7d3ef --- /dev/null +++ b/server/src/docs/asciidoc/memberBillReport.adoc @@ -0,0 +1,17 @@ +== ์ •์‚ฐ + +=== ์ฐธ์—ฌ์ž๋ณ„ ์ •์‚ฐ ๊ฒฐ๊ณผ ์กฐํšŒ + +operation::getMemberBillReports[snippets="path-parameters,http-request,response-body,response-fields,http-response,http-request"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"EVENT_NOT_FOUND", + "message":"์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค." + } +] +---- diff --git a/server/src/main/java/server/haengdong/HaengdongApplication.java b/server/src/main/java/server/haengdong/HaengdongApplication.java new file mode 100644 index 000000000..4a84c6120 --- /dev/null +++ b/server/src/main/java/server/haengdong/HaengdongApplication.java @@ -0,0 +1,15 @@ +package server.haengdong; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@Slf4j +@SpringBootApplication +public class HaengdongApplication { + + public static void main(String[] args) { + SpringApplication.run(HaengdongApplication.class, args); + } + +} diff --git a/server/src/main/java/server/haengdong/application/ActionService.java b/server/src/main/java/server/haengdong/application/ActionService.java new file mode 100644 index 000000000..bcf5e8b55 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/ActionService.java @@ -0,0 +1,39 @@ +package server.haengdong.application; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import server.haengdong.application.response.MemberBillReportAppResponse; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.action.MemberBillReport; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@RequiredArgsConstructor +@Transactional(readOnly = true) +@Service +public class ActionService { + + private final BillActionRepository billActionRepository; + private final MemberActionRepository memberActionRepository; + private final EventRepository eventRepository; + + public List<MemberBillReportAppResponse> getMemberBillReports(String token) { + Event event = eventRepository.findByToken(token) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); + List<BillAction> billActions = billActionRepository.findByAction_Event(event); + List<MemberAction> memberActions = memberActionRepository.findAllByEvent(event); + + MemberBillReport memberBillReport = MemberBillReport.createByActions(billActions, memberActions); + + return memberBillReport.getReports().entrySet().stream() + .map(entry -> new MemberBillReportAppResponse(entry.getKey(), entry.getValue())) + .toList(); + } +} diff --git a/server/src/main/java/server/haengdong/application/AuthService.java b/server/src/main/java/server/haengdong/application/AuthService.java new file mode 100644 index 000000000..d9352ad53 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/AuthService.java @@ -0,0 +1,41 @@ +package server.haengdong.application; + + +import java.util.Map; +import server.haengdong.domain.TokenProvider; +import server.haengdong.exception.AuthenticationException; +import server.haengdong.exception.HaengdongErrorCode; + +public class AuthService { + + private static final String TOKEN_NAME = "eventToken"; + private static final String CLAIM_SUB = "sub"; + + private final TokenProvider tokenProvider; + + public AuthService(TokenProvider tokenProvider) { + this.tokenProvider = tokenProvider; + } + + public String createToken(String eventId) { + Map<String, Object> payload = Map.of(CLAIM_SUB, eventId); + + return tokenProvider.createToken(payload); + } + + public String findEventIdByToken(String token) { + validateToken(token); + Map<String, Object> payload = tokenProvider.getPayload(token); + return (String) payload.get(CLAIM_SUB); + } + + private void validateToken(String token) { + if (!tokenProvider.validateToken(token)) { + throw new AuthenticationException(HaengdongErrorCode.TOKEN_INVALID); + } + } + + public String getTokenName() { + return TOKEN_NAME; + } +} diff --git a/server/src/main/java/server/haengdong/application/BillActionDetailService.java b/server/src/main/java/server/haengdong/application/BillActionDetailService.java new file mode 100644 index 000000000..55d39aac0 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/BillActionDetailService.java @@ -0,0 +1,76 @@ +package server.haengdong.application; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import server.haengdong.application.request.BillActionDetailUpdateAppRequest; +import server.haengdong.application.request.BillActionDetailsUpdateAppRequest; +import server.haengdong.application.response.BillActionDetailsAppResponse; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionDetail; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@RequiredArgsConstructor +@Transactional(readOnly = true) +@Service +public class BillActionDetailService { + + private final BillActionRepository billActionRepository; + + public BillActionDetailsAppResponse findBillActionDetails(String token, Long actionId) { + BillAction billAction = billActionRepository.findByAction_Id(actionId) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.BILL_ACTION_NOT_FOUND)); + validateToken(token, billAction); + + List<BillActionDetail> billActionDetails = billAction.getBillActionDetails(); + return BillActionDetailsAppResponse.of(billActionDetails); + } + + @Transactional + public void updateBillActionDetails(String token, Long actionId, BillActionDetailsUpdateAppRequest request) { + BillAction billAction = billActionRepository.findByAction_Id(actionId) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.BILL_ACTION_NOT_FOUND)); + + List<BillActionDetailUpdateAppRequest> billActionDetailUpdateAppRequests = request.billActionDetailUpdateAppRequests(); + + validateToken(token, billAction); + validateTotalPrice(billActionDetailUpdateAppRequests, billAction); + + List<BillActionDetail> billActionDetails = billAction.getBillActionDetails(); + + for (BillActionDetailUpdateAppRequest updateRequest : billActionDetailUpdateAppRequests) { + BillActionDetail detailToUpdate = billActionDetails.stream() + .filter(detail -> detail.isSameName(updateRequest.name())) + .findFirst() + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.BILL_ACTION_DETAIL_NOT_FOUND)); + + detailToUpdate.updatePrice(updateRequest.price()); + detailToUpdate.updateIsFixed(updateRequest.isFixed()); + } + } + + private void validateToken(String token, BillAction billAction) { + Event event = billAction.getEvent(); + if (event.isTokenMismatch(token)) { + throw new HaengdongException(HaengdongErrorCode.BILL_ACTION_NOT_FOUND); + } + } + + private void validateTotalPrice(List<BillActionDetailUpdateAppRequest> billActionDetailUpdateAppRequests, + BillAction billAction) { + Long requestsPriceSum = calculateUpdatePriceSum(billActionDetailUpdateAppRequests); + if (!billAction.isSamePrice(requestsPriceSum)) { + throw new HaengdongException(HaengdongErrorCode.BILL_ACTION_PRICE_NOT_MATCHED); + } + } + + private Long calculateUpdatePriceSum(List<BillActionDetailUpdateAppRequest> billActionDetailUpdateAppRequests) { + return billActionDetailUpdateAppRequests.stream() + .map(BillActionDetailUpdateAppRequest::price) + .reduce(0L, Long::sum); + } +} diff --git a/server/src/main/java/server/haengdong/application/BillActionService.java b/server/src/main/java/server/haengdong/application/BillActionService.java new file mode 100644 index 000000000..dae36a2e7 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/BillActionService.java @@ -0,0 +1,80 @@ +package server.haengdong.application; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import server.haengdong.application.request.BillActionAppRequest; +import server.haengdong.application.request.BillActionUpdateAppRequest; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.ActionRepository; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.CurrentMembers; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@RequiredArgsConstructor +@Transactional(readOnly = true) +@Service +public class BillActionService { + + private final BillActionRepository billActionRepository; + private final MemberActionRepository memberActionRepository; + private final ActionRepository actionRepository; + private final EventRepository eventRepository; + + @Transactional + public void saveAllBillAction(String eventToken, List<BillActionAppRequest> requests) { + Event event = getEvent(eventToken); + Action action = createStartAction(event); + List<MemberAction> findMemberActions = memberActionRepository.findAllByEvent(event); + CurrentMembers currentMembers = CurrentMembers.of(findMemberActions); + + for (BillActionAppRequest request : requests) { + BillAction billAction = request.toBillAction(action, currentMembers); + billActionRepository.save(billAction); + action = action.next(); + } + } + + private Action createStartAction(Event event) { + return actionRepository.findLastByEvent(event) + .map(Action::next) + .orElse(Action.createFirst(event)); + } + + @Transactional + public void updateBillAction(String token, Long actionId, BillActionUpdateAppRequest request) { + BillAction billAction = billActionRepository.findByAction_Id(actionId) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.BILL_ACTION_NOT_FOUND)); + + validateToken(token, billAction); + + billAction.update(request.title(), request.price()); + } + + private void validateToken(String token, BillAction billAction) { + Event event = billAction.getEvent(); + if (event.isTokenMismatch(token)) { + throw new HaengdongException(HaengdongErrorCode.BILL_ACTION_NOT_FOUND); + } + } + + @Transactional + public void deleteBillAction(String token, Long actionId) { + Event event = eventRepository.findByToken(token) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); + + billActionRepository.deleteByAction_EventAndActionId(event, actionId); + } + + private Event getEvent(String eventToken) { + return eventRepository.findByToken(eventToken) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); + } +} diff --git a/server/src/main/java/server/haengdong/application/EventService.java b/server/src/main/java/server/haengdong/application/EventService.java new file mode 100644 index 000000000..1aaddd0f9 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/EventService.java @@ -0,0 +1,170 @@ +package server.haengdong.application; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Set; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import server.haengdong.application.request.EventAppRequest; +import server.haengdong.application.request.EventLoginAppRequest; +import server.haengdong.application.request.MemberNameUpdateAppRequest; +import server.haengdong.application.request.MemberNamesUpdateAppRequest; +import server.haengdong.application.response.ActionAppResponse; +import server.haengdong.application.response.EventAppResponse; +import server.haengdong.application.response.EventDetailAppResponse; +import server.haengdong.application.response.MembersAppResponse; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionDetailRepository; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.domain.event.EventTokenProvider; +import server.haengdong.exception.AuthenticationException; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@RequiredArgsConstructor +@Transactional(readOnly = true) +@Service +public class EventService { + + private final EventRepository eventRepository; + private final EventTokenProvider eventTokenProvider; + private final BillActionRepository billActionRepository; + private final MemberActionRepository memberActionRepository; + private final BillActionDetailRepository billActionDetailRepository; + + + @Transactional + public EventAppResponse saveEvent(EventAppRequest request) { + String token = eventTokenProvider.createToken(); + Event event = request.toEvent(token); + eventRepository.save(event); + + return EventAppResponse.of(event); + } + + public EventDetailAppResponse findEvent(String token) { + Event event = getEvent(token); + + return EventDetailAppResponse.of(event); + } + + public List<ActionAppResponse> findActions(String token) { + Event event = getEvent(token); + + List<BillAction> billActions = billActionRepository.findByAction_Event(event).stream() + .sorted(Comparator.comparing(BillAction::getSequence)).toList(); + List<MemberAction> memberActions = memberActionRepository.findAllByEvent(event).stream() + .sorted(Comparator.comparing(MemberAction::getSequence)).toList(); + + return getActionAppResponses(billActions, memberActions); + } + + private List<ActionAppResponse> getActionAppResponses( + List<BillAction> billActions, + List<MemberAction> memberActions + ) { + int billActionIndex = 0; + int memberActionIndex = 0; + List<ActionAppResponse> actionAppResponses = new ArrayList<>(); + + while (billActionIndex < billActions.size() && memberActionIndex < memberActions.size()) { + BillAction billAction = billActions.get(billActionIndex); + MemberAction memberAction = memberActions.get(memberActionIndex); + if (billAction.getSequence() < memberAction.getSequence()) { + actionAppResponses.add(ActionAppResponse.of(billAction)); + billActionIndex++; + } else { + actionAppResponses.add(ActionAppResponse.of(memberAction)); + memberActionIndex++; + } + } + while (billActionIndex < billActions.size()) { + BillAction billAction = billActions.get(billActionIndex++); + actionAppResponses.add(ActionAppResponse.of(billAction)); + } + while (memberActionIndex < memberActions.size()) { + MemberAction memberAction = memberActions.get(memberActionIndex++); + actionAppResponses.add(ActionAppResponse.of(memberAction)); + } + + return actionAppResponses; + } + + public MembersAppResponse findAllMembers(String token) { + Event event = getEvent(token); + + List<String> memberNames = memberActionRepository.findAllUniqueMemberByEvent(event); + + return new MembersAppResponse(memberNames); + } + + @Transactional + public void updateMember(String token, MemberNamesUpdateAppRequest request) { + Event event = getEvent(token); + List<MemberNameUpdateAppRequest> members = request.members(); + + validateBeforeNames(members, event); + validateAfterNames(members, event); + + members.forEach(member -> updateMemberName(event, member.before(), member.after())); + } + + private void validateBeforeNames(List<MemberNameUpdateAppRequest> members, Event event) { + List<String> beforeNames = members.stream() + .map(MemberNameUpdateAppRequest::before) + .toList(); + if (beforeNames.size() != Set.copyOf(beforeNames).size()) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_CHANGE_DUPLICATE); + } + beforeNames.forEach(beforeName -> validateBeforeMemberNameExist(event, beforeName)); + } + + private void validateBeforeMemberNameExist(Event event, String beforeName) { + boolean isMemberNameExist = memberActionRepository.existsByAction_EventAndMemberName(event, beforeName); + if (!isMemberNameExist) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_NOT_EXIST); + } + } + + private void validateAfterNames(List<MemberNameUpdateAppRequest> members, Event event) { + List<String> afterNames = members.stream() + .map(MemberNameUpdateAppRequest::after) + .toList(); + if (afterNames.size() != Set.copyOf(afterNames).size()) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_CHANGE_DUPLICATE); + } + afterNames.forEach(afterName -> validateAfterMemberNameNotExist(event, afterName)); + } + + private void validateAfterMemberNameNotExist(Event event, String afterName) { + boolean isMemberNameExist = memberActionRepository.existsByAction_EventAndMemberName(event, afterName); + if (isMemberNameExist) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_DUPLICATE); + } + } + + private void updateMemberName(Event event, String beforeName, String afterName) { + memberActionRepository.findAllByAction_EventAndMemberName(event, beforeName) + .forEach(memberAction -> memberAction.updateMemberName(afterName)); + billActionDetailRepository.findAllByBillAction_Action_EventAndMemberName(event, beforeName) + .forEach(billActionDetail -> billActionDetail.updateMemberName(afterName)); + } + + public void validatePassword(EventLoginAppRequest request) throws HaengdongException { + Event event = getEvent(request.token()); + if (event.isPasswordMismatch(request.password())) { + throw new AuthenticationException(HaengdongErrorCode.PASSWORD_INVALID); + } + } + + private Event getEvent(String token) { + return eventRepository.findByToken(token) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); + } +} diff --git a/server/src/main/java/server/haengdong/application/MemberActionFactory.java b/server/src/main/java/server/haengdong/application/MemberActionFactory.java new file mode 100644 index 000000000..c0a171642 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/MemberActionFactory.java @@ -0,0 +1,62 @@ +package server.haengdong.application; + +import java.util.ArrayList; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import server.haengdong.application.request.MemberActionSaveAppRequest; +import server.haengdong.application.request.MemberActionsSaveAppRequest; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.CurrentMembers; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionStatus; +import server.haengdong.domain.action.MemberGroupIdProvider; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@RequiredArgsConstructor +@Component +public class MemberActionFactory { + + private final MemberGroupIdProvider memberGroupIdProvider; + + public List<MemberAction> createMemberActions( + MemberActionsSaveAppRequest request, + CurrentMembers currentMembers, + Action action + ) { + validateMemberNames(request); + validateActions(request, currentMembers); + + Long memberGroupId = memberGroupIdProvider.createGroupId(); + List<MemberAction> createdMemberActions = new ArrayList<>(); + List<MemberActionSaveAppRequest> actions = request.actions(); + for (MemberActionSaveAppRequest appRequest : actions) { + MemberAction memberAction = appRequest.toMemberAction(action, memberGroupId); + createdMemberActions.add(memberAction); + action = action.next(); + } + + return createdMemberActions; + } + + private void validateMemberNames(MemberActionsSaveAppRequest request) { + List<String> memberNames = request.actions().stream() + .map(MemberActionSaveAppRequest::name) + .toList(); + + long uniqueCount = memberNames.stream().distinct().count(); + if (uniqueCount != memberNames.size()) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_DUPLICATE); + } + } + + private void validateActions(MemberActionsSaveAppRequest request, CurrentMembers currentMembers) { + List<MemberActionSaveAppRequest> actions = request.actions(); + + for (MemberActionSaveAppRequest action : actions) { + MemberActionStatus memberActionStatus = MemberActionStatus.of(action.status()); + currentMembers.validate(action.name(), memberActionStatus); + } + } +} diff --git a/server/src/main/java/server/haengdong/application/MemberActionService.java b/server/src/main/java/server/haengdong/application/MemberActionService.java new file mode 100644 index 000000000..245de8cef --- /dev/null +++ b/server/src/main/java/server/haengdong/application/MemberActionService.java @@ -0,0 +1,100 @@ +package server.haengdong.application; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import server.haengdong.application.request.MemberActionsSaveAppRequest; +import server.haengdong.application.response.CurrentMemberAppResponse; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.ActionRepository; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.CurrentMembers; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@RequiredArgsConstructor +@Transactional(readOnly = true) +@Service +public class MemberActionService { + + private final MemberActionFactory memberActionFactory; + private final MemberActionRepository memberActionRepository; + private final EventRepository eventRepository; + private final ActionRepository actionRepository; + private final BillActionRepository billActionRepository; + + @Transactional + public void saveMemberAction(String token, MemberActionsSaveAppRequest request) { + Event event = findEvent(token); + + List<MemberAction> findMemberActions = memberActionRepository.findAllByEvent(event); + CurrentMembers currentMembers = CurrentMembers.of(findMemberActions); + Action action = createStartAction(event); + List<MemberAction> memberActions = memberActionFactory.createMemberActions(request, currentMembers, action); + memberActionRepository.saveAll(memberActions); + } + + private Action createStartAction(Event event) { + return actionRepository.findLastByEvent(event) + .map(Action::next) + .orElse(Action.createFirst(event)); + } + + public List<CurrentMemberAppResponse> getCurrentMembers(String token) { + Event event = findEvent(token); + List<MemberAction> findMemberActions = memberActionRepository.findAllByEvent(event); + CurrentMembers currentMembers = CurrentMembers.of(findMemberActions); + + return currentMembers.getMembers() + .stream() + .map(CurrentMemberAppResponse::new) + .toList(); + } + + private Event findEvent(String token) { + return eventRepository.findByToken(token) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); + } + + @Transactional + public void deleteMember(String token, String memberName) { + Event event = eventRepository.findByToken(token) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); + + memberActionRepository.deleteAllByEventAndMemberName(event, memberName); + + List<BillAction> billActions = billActionRepository.findByAction_Event(event); + billActions.forEach(billAction -> resetBillAction(event, billAction)); + } + + @Transactional + public void deleteMemberAction(String token, Long actionId) { + Event event = eventRepository.findByToken(token) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); + Action action = actionRepository.findByIdAndEvent(actionId, event) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.ACTION_NOT_FOUND)); + MemberAction memberAction = memberActionRepository.findByAction(action) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.MEMBER_ACTION_NOT_FOUND)); + + memberActionRepository.deleteAllByMemberNameAndMinSequence(memberAction.getMemberName(), + memberAction.getSequence()); + + List<BillAction> billActions = billActionRepository.findByEventAndGreaterThanSequence(event, + action.getSequence()); + billActions.forEach(billAction -> resetBillAction(event, billAction)); + } + + private void resetBillAction(Event event, BillAction billAction) { + List<MemberAction> memberActions = memberActionRepository.findByEventAndSequence(event, + billAction.getSequence()); + CurrentMembers currentMembers = CurrentMembers.of(memberActions); + + billAction.resetBillActionDetails(currentMembers); + } +} diff --git a/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java b/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java new file mode 100644 index 000000000..21eb17d4a --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java @@ -0,0 +1,15 @@ +package server.haengdong.application.request; + +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.CurrentMembers; + +public record BillActionAppRequest( + String title, + Long price +) { + + public BillAction toBillAction(Action action, CurrentMembers currentMembers) { + return BillAction.create(action, title, price, currentMembers); + } +} diff --git a/server/src/main/java/server/haengdong/application/request/BillActionDetailUpdateAppRequest.java b/server/src/main/java/server/haengdong/application/request/BillActionDetailUpdateAppRequest.java new file mode 100644 index 000000000..e514aee81 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/BillActionDetailUpdateAppRequest.java @@ -0,0 +1,8 @@ +package server.haengdong.application.request; + +public record BillActionDetailUpdateAppRequest( + String name, + Long price, + boolean isFixed +) { +} diff --git a/server/src/main/java/server/haengdong/application/request/BillActionDetailsUpdateAppRequest.java b/server/src/main/java/server/haengdong/application/request/BillActionDetailsUpdateAppRequest.java new file mode 100644 index 000000000..1fe19798e --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/BillActionDetailsUpdateAppRequest.java @@ -0,0 +1,8 @@ +package server.haengdong.application.request; + +import java.util.List; + +public record BillActionDetailsUpdateAppRequest( + List<BillActionDetailUpdateAppRequest> billActionDetailUpdateAppRequests +) { +} diff --git a/server/src/main/java/server/haengdong/application/request/BillActionUpdateAppRequest.java b/server/src/main/java/server/haengdong/application/request/BillActionUpdateAppRequest.java new file mode 100644 index 000000000..a90e3dd42 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/BillActionUpdateAppRequest.java @@ -0,0 +1,7 @@ +package server.haengdong.application.request; + +public record BillActionUpdateAppRequest( + String title, + Long price +) { +} diff --git a/server/src/main/java/server/haengdong/application/request/EventAppRequest.java b/server/src/main/java/server/haengdong/application/request/EventAppRequest.java new file mode 100644 index 000000000..20ec16d88 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/EventAppRequest.java @@ -0,0 +1,10 @@ +package server.haengdong.application.request; + +import server.haengdong.domain.event.Event; + +public record EventAppRequest(String name, String password) { + + public Event toEvent(String token) { + return new Event(name, password, token); + } +} diff --git a/server/src/main/java/server/haengdong/application/request/EventLoginAppRequest.java b/server/src/main/java/server/haengdong/application/request/EventLoginAppRequest.java new file mode 100644 index 000000000..947b5ef39 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/EventLoginAppRequest.java @@ -0,0 +1,4 @@ +package server.haengdong.application.request; + +public record EventLoginAppRequest(String token, String password) { +} diff --git a/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java new file mode 100644 index 000000000..f7f8d8fc2 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java @@ -0,0 +1,12 @@ +package server.haengdong.application.request; + +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionStatus; + +public record MemberActionSaveAppRequest(String name, String status) { + + public MemberAction toMemberAction(Action action, Long memberGroupId) { + return new MemberAction(action, name, MemberActionStatus.of(status), memberGroupId); + } +} diff --git a/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java new file mode 100644 index 000000000..650b908df --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java @@ -0,0 +1,6 @@ +package server.haengdong.application.request; + +import java.util.List; + +public record MemberActionsSaveAppRequest(List<MemberActionSaveAppRequest> actions) { +} diff --git a/server/src/main/java/server/haengdong/application/request/MemberNameUpdateAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberNameUpdateAppRequest.java new file mode 100644 index 000000000..d629d3a02 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/MemberNameUpdateAppRequest.java @@ -0,0 +1,7 @@ +package server.haengdong.application.request; + +public record MemberNameUpdateAppRequest( + String before, + String after +) { +} diff --git a/server/src/main/java/server/haengdong/application/request/MemberNamesUpdateAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberNamesUpdateAppRequest.java new file mode 100644 index 000000000..cd0c00544 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/MemberNamesUpdateAppRequest.java @@ -0,0 +1,8 @@ +package server.haengdong.application.request; + +import java.util.List; + +public record MemberNamesUpdateAppRequest( + List<MemberNameUpdateAppRequest> members +) { +} diff --git a/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java b/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java new file mode 100644 index 000000000..0c2c12611 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java @@ -0,0 +1,61 @@ +package server.haengdong.application.response; + +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionStatus; + +public record ActionAppResponse( + Long actionId, + String name, + Long price, + Long sequence, + boolean isFixed, + ActionType actionType +) { + + public ActionAppResponse(Long actionId, String name, Long price, Long sequence, ActionType actionType) { + this(actionId, name, price, sequence, false, actionType); + } + + public static ActionAppResponse of(BillAction billAction) { + return new ActionAppResponse( + billAction.getAction().getId(), + billAction.getTitle(), + billAction.getPrice(), + billAction.getSequence(), + billAction.isFixed(), + ActionAppResponse.ActionType.BILL + ); + } + + public static ActionAppResponse of(MemberAction memberAction) { + MemberActionStatus status = memberAction.getStatus(); + + return new ActionAppResponse( + memberAction.getAction().getId(), + memberAction.getMemberName(), + null, + memberAction.getSequence(), + false, + ActionAppResponse.ActionType.of(status) + ); + } + + public String actionTypeName() { + return actionType.name(); + } + + public enum ActionType { + BILL, + IN, + OUT, + ; + + private static ActionType of(MemberActionStatus memberActionStatus) { + if (MemberActionStatus.IN == memberActionStatus) { + return IN; + } + return OUT; + } + } +} diff --git a/server/src/main/java/server/haengdong/application/response/BillActionDetailAppResponse.java b/server/src/main/java/server/haengdong/application/response/BillActionDetailAppResponse.java new file mode 100644 index 000000000..3efc7ac9d --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/BillActionDetailAppResponse.java @@ -0,0 +1,18 @@ +package server.haengdong.application.response; + +import server.haengdong.domain.action.BillActionDetail; + +public record BillActionDetailAppResponse( + String name, + Long price, + boolean isFixed +) { + + public static BillActionDetailAppResponse of(BillActionDetail billActionDetail) { + return new BillActionDetailAppResponse( + billActionDetail.getMemberName(), + billActionDetail.getPrice(), + billActionDetail.isFixed() + ); + } +} diff --git a/server/src/main/java/server/haengdong/application/response/BillActionDetailsAppResponse.java b/server/src/main/java/server/haengdong/application/response/BillActionDetailsAppResponse.java new file mode 100644 index 000000000..061f07816 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/BillActionDetailsAppResponse.java @@ -0,0 +1,14 @@ +package server.haengdong.application.response; + +import java.util.List; +import java.util.stream.Collectors; +import server.haengdong.domain.action.BillActionDetail; + +public record BillActionDetailsAppResponse(List<BillActionDetailAppResponse> billActionDetailAppResponses) { + + public static BillActionDetailsAppResponse of(List<BillActionDetail> billActionDetails) { + return billActionDetails.stream() + .map(BillActionDetailAppResponse::of) + .collect(Collectors.collectingAndThen(Collectors.toList(), BillActionDetailsAppResponse::new)); + } +} diff --git a/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java b/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java new file mode 100644 index 000000000..6c682d3e9 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.application.response; + +import server.haengdong.domain.action.MemberAction; + +public record CurrentMemberAppResponse(String name) { + + public static CurrentMemberAppResponse of(MemberAction memberAction) { + return new CurrentMemberAppResponse(memberAction.getMemberName()); + } +} diff --git a/server/src/main/java/server/haengdong/application/response/EventAppResponse.java b/server/src/main/java/server/haengdong/application/response/EventAppResponse.java new file mode 100644 index 000000000..f331d0011 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/EventAppResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.application.response; + +import server.haengdong.domain.event.Event; + +public record EventAppResponse(String token) { + + public static EventAppResponse of(Event event) { + return new EventAppResponse(event.getToken()); + } +} diff --git a/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java b/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java new file mode 100644 index 000000000..6e38826d4 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.application.response; + +import server.haengdong.domain.event.Event; + +public record EventDetailAppResponse(String eventName) { + + public static EventDetailAppResponse of(Event event) { + return new EventDetailAppResponse(event.getName()); + } +} diff --git a/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java b/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java new file mode 100644 index 000000000..21b6cef56 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java @@ -0,0 +1,4 @@ +package server.haengdong.application.response; + +public record MemberBillReportAppResponse(String name, Long price) { +} diff --git a/server/src/main/java/server/haengdong/application/response/MembersAppResponse.java b/server/src/main/java/server/haengdong/application/response/MembersAppResponse.java new file mode 100644 index 000000000..be8378b37 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/MembersAppResponse.java @@ -0,0 +1,8 @@ +package server.haengdong.application.response; + +import java.util.List; + +public record MembersAppResponse( + List<String> memberNames +) { +} diff --git a/server/src/main/java/server/haengdong/config/AdminInterceptor.java b/server/src/main/java/server/haengdong/config/AdminInterceptor.java new file mode 100644 index 000000000..a0542ed46 --- /dev/null +++ b/server/src/main/java/server/haengdong/config/AdminInterceptor.java @@ -0,0 +1,51 @@ +package server.haengdong.config; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpMethod; +import org.springframework.web.servlet.HandlerInterceptor; +import server.haengdong.application.AuthService; +import server.haengdong.exception.AuthenticationException; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.infrastructure.auth.AuthenticationExtractor; + +@Slf4j +public class AdminInterceptor implements HandlerInterceptor { + + private final AuthService authService; + private final AuthenticationExtractor authenticationExtractor; + + public AdminInterceptor(AuthService authService, AuthenticationExtractor authenticationExtractor) { + this.authService = authService; + this.authenticationExtractor = authenticationExtractor; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + String requestURI = request.getRequestURI(); + + if (requestURI.endsWith("/login")) { + return true; // ์š”์ฒญ์„ ๊ณ„์† ์ง„ํ–‰ํ•˜๋„๋ก ํ—ˆ์šฉ + } + + HttpMethod method = HttpMethod.valueOf(request.getMethod()); + if (HttpMethod.GET.equals(method) || HttpMethod.OPTIONS.equals(method)) { + return true; + } + + validateToken(request); + + return true; + } + + private void validateToken(HttpServletRequest request) { + String token = authenticationExtractor.extract(request, authService.getTokenName()); + String tokenEventId = authService.findEventIdByToken(token); + String eventId = request.getRequestURI().split("/")[3]; + if (!tokenEventId.equals(eventId)) { + log.warn("[ํ–‰์‚ฌ ์ ‘๊ทผ ๋ถˆ๊ฐ€] Cookie EventId = {}, URL EventId = {}", tokenEventId, eventId); + throw new AuthenticationException(HaengdongErrorCode.FORBIDDEN); + } + } +} diff --git a/server/src/main/java/server/haengdong/config/RequestServletFilter.java b/server/src/main/java/server/haengdong/config/RequestServletFilter.java new file mode 100644 index 000000000..b1afdb6f8 --- /dev/null +++ b/server/src/main/java/server/haengdong/config/RequestServletFilter.java @@ -0,0 +1,23 @@ +package server.haengdong.config; + +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import java.io.IOException; +import org.springframework.stereotype.Component; +import org.springframework.web.util.ContentCachingRequestWrapper; + +@Component +public class RequestServletFilter implements Filter { + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper((HttpServletRequest) request); + + chain.doFilter(wrappedRequest, response); + } +} diff --git a/server/src/main/java/server/haengdong/config/WebMvcConfig.java b/server/src/main/java/server/haengdong/config/WebMvcConfig.java new file mode 100644 index 000000000..d1caa176f --- /dev/null +++ b/server/src/main/java/server/haengdong/config/WebMvcConfig.java @@ -0,0 +1,66 @@ +package server.haengdong.config; + +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import server.haengdong.application.AuthService; +import server.haengdong.domain.TokenProvider; +import server.haengdong.infrastructure.auth.AuthenticationExtractor; +import server.haengdong.infrastructure.auth.JwtTokenProvider; +import server.haengdong.infrastructure.auth.TokenProperties; + +@RequiredArgsConstructor +@EnableConfigurationProperties(TokenProperties.class) +@Configuration +public class WebMvcConfig implements WebMvcConfigurer { + + private final TokenProperties tokenProperties; + + @Value("${cors.max-age}") + private Long maxAge; + + @Value("${cors.allowed-origins}") + private String[] allowedOrigins; + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins(allowedOrigins) + .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS") + .allowedHeaders("*") + .allowCredentials(true) + .maxAge(maxAge); + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(adminInterceptor()) + .addPathPatterns("/api/**") + .excludePathPatterns("/api/events"); + } + + @Bean + public AdminInterceptor adminInterceptor() { + return new AdminInterceptor(authService(), authenticationExtractor()); + } + + @Bean + public AuthService authService() { + return new AuthService(tokenProvider()); + } + + @Bean + public TokenProvider tokenProvider() { + return new JwtTokenProvider(tokenProperties); + } + + @Bean + public AuthenticationExtractor authenticationExtractor() { + return new AuthenticationExtractor(); + } +} diff --git a/server/src/main/java/server/haengdong/domain/TokenProvider.java b/server/src/main/java/server/haengdong/domain/TokenProvider.java new file mode 100644 index 000000000..28e7956c3 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/TokenProvider.java @@ -0,0 +1,12 @@ +package server.haengdong.domain; + +import java.util.Map; + +public interface TokenProvider { + + String createToken(Map<String, Object> payload); + + Map<String, Object> getPayload(String token); + + boolean validateToken(String token); +} diff --git a/server/src/main/java/server/haengdong/domain/action/Action.java b/server/src/main/java/server/haengdong/domain/action/Action.java new file mode 100644 index 000000000..11f91fc38 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/Action.java @@ -0,0 +1,42 @@ +package server.haengdong.domain.action; + +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import server.haengdong.domain.event.Event; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class Action { + + private static final long FIRST_SEQUENCE = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + private Event event; + + private Long sequence; + + public Action(Event event, Long sequence) { + this.event = event; + this.sequence = sequence; + } + + public static Action createFirst(Event event) { + return new Action(event, FIRST_SEQUENCE); + } + + public Action next() { + return new Action(event, sequence + 1); + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/ActionRepository.java b/server/src/main/java/server/haengdong/domain/action/ActionRepository.java new file mode 100644 index 000000000..2fde0ffa6 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/ActionRepository.java @@ -0,0 +1,23 @@ +package server.haengdong.domain.action; + +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; +import server.haengdong.domain.event.Event; + +@Repository +public interface ActionRepository extends JpaRepository<Action, Long> { + + @Query(""" + SELECT a + FROM Action a + WHERE a.event = :event + ORDER BY a.sequence DESC + LIMIT 1 + """) + Optional<Action> findLastByEvent(@Param("event") Event event); + + Optional<Action> findByIdAndEvent(Long id, Event event); +} diff --git a/server/src/main/java/server/haengdong/domain/action/BillAction.java b/server/src/main/java/server/haengdong/domain/action/BillAction.java new file mode 100644 index 000000000..943b40ce5 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/BillAction.java @@ -0,0 +1,156 @@ +package server.haengdong.domain.action; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import server.haengdong.domain.event.Event; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class BillAction implements Comparable<BillAction> { + + public static final int MIN_TITLE_LENGTH = 1; + public static final int MAX_TITLE_LENGTH = 30; + public static final long MIN_PRICE = 1L; + public static final long MAX_PRICE = 10_000_000L; + private static final long DEFAULT_PRICE = 0L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) + private Action action; + + @Column(length = MAX_TITLE_LENGTH) + private String title; + + private Long price; + + @OneToMany(mappedBy = "billAction", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + private List<BillActionDetail> billActionDetails = new ArrayList<>(); + + public BillAction(Action action, String title, Long price) { + validateTitle(title); + validatePrice(price); + this.action = action; + this.title = title.trim(); + this.price = price; + } + + private void validateTitle(String title) { + int titleLength = title.trim().length(); + if (titleLength < MIN_TITLE_LENGTH || titleLength > MAX_TITLE_LENGTH) { + throw new HaengdongException(HaengdongErrorCode.BILL_ACTION_TITLE_INVALID); + } + } + + private void validatePrice(Long price) { + if (price < MIN_PRICE || price > MAX_PRICE) { + throw new HaengdongException(HaengdongErrorCode.BILL_ACTION_PRICE_INVALID); + } + } + + public static BillAction create(Action action, String title, Long price, CurrentMembers currentMembers) { + BillAction billAction = new BillAction(action, title, price); + billAction.resetBillActionDetails(currentMembers); + return billAction; + } + + public void resetBillActionDetails(CurrentMembers currentMembers) { + this.billActionDetails.clear(); + Iterator<Long> priceIterator = distributePrice(currentMembers.size()).iterator(); + + for (String member : currentMembers.getMembers()) { + BillActionDetail billActionDetail = new BillActionDetail(this, member, priceIterator.next(), false); + this.billActionDetails.add(billActionDetail); + } + } + + private void resetBillActionDetails() { + Iterator<Long> priceIterator = distributePrice(billActionDetails.size()).iterator(); + + billActionDetails.forEach(billActionDetail -> { + billActionDetail.updatePrice(priceIterator.next()); + billActionDetail.updateIsFixed(false); + }); + } + + private List<Long> distributePrice(int memberCount) { + if (memberCount == 0) { + return new ArrayList<>(); + } + long eachPrice = price / memberCount; + long remainder = price % memberCount; + + List<Long> results = Stream.generate(() -> eachPrice) + .limit(memberCount - 1) + .collect(Collectors.toList()); + results.add(eachPrice + remainder); + return results; + } + + public void update(String title, Long price) { + validateTitle(title); + validatePrice(price); + this.title = title.trim(); + this.price = price; + resetBillActionDetails(); + } + + public void addDetails(List<BillActionDetail> billActionDetails) { + billActionDetails.forEach(this::addDetail); + } + + private void addDetail(BillActionDetail billActionDetail) { + this.billActionDetails.add(billActionDetail); + billActionDetail.setBillAction(this); + } + + public boolean isFixed() { + return billActionDetails.stream() + .anyMatch(BillActionDetail::isFixed); + } + + public boolean isSamePrice(Long price) { + return this.price.equals(price); + } + + public Long findPriceByMemberName(String memberName) { + return billActionDetails.stream() + .filter(billActionDetail -> billActionDetail.hasMemberName(memberName)) + .map(BillActionDetail::getPrice) + .findFirst() + .orElse(DEFAULT_PRICE); + } + + public Long getSequence() { + return action.getSequence(); + } + + public Event getEvent() { + return action.getEvent(); + } + + @Override + public int compareTo(BillAction o) { + return Long.compare(this.getSequence(), o.getSequence()); + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/BillActionDetail.java b/server/src/main/java/server/haengdong/domain/action/BillActionDetail.java new file mode 100644 index 000000000..ffdfe04a3 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/BillActionDetail.java @@ -0,0 +1,61 @@ +package server.haengdong.domain.action; + +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class BillActionDetail { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + private BillAction billAction; + + private String memberName; + + private Long price; + + private boolean isFixed; + + public BillActionDetail(BillAction billAction, String memberName, Long price, boolean isFixed) { + this.billAction = billAction; + this.memberName = memberName; + this.price = price; + this.isFixed = isFixed; + } + + public void updatePrice(Long price) { + this.price = price; + } + + public void updateIsFixed(boolean isFixed) { + this.isFixed = isFixed; + } + + public void updateMemberName(String name) { + this.memberName = name; + } + + public boolean hasMemberName(String memberName) { + return this.memberName.equals(memberName); + } + + public boolean isSameName(String memberName) { + return this.memberName.equals(memberName); + } + + public void setBillAction(BillAction billAction) { + this.billAction = billAction; + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java b/server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java new file mode 100644 index 000000000..05de55304 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java @@ -0,0 +1,20 @@ +package server.haengdong.domain.action; + +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; +import server.haengdong.domain.event.Event; + +@Repository +public interface BillActionDetailRepository extends JpaRepository<BillActionDetail, Long> { + + @Query(""" + select bd + from BillActionDetail bd + where bd.billAction = :billAction + """) + List<BillActionDetail> findAllByBillAction(BillAction billAction); + + List<BillActionDetail> findAllByBillAction_Action_EventAndMemberName(Event event, String memberName); +} diff --git a/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java b/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java new file mode 100644 index 000000000..817a63bf8 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java @@ -0,0 +1,27 @@ +package server.haengdong.domain.action; + +import java.util.List; +import java.util.Optional; +import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; +import server.haengdong.domain.event.Event; + +@Repository +public interface BillActionRepository extends JpaRepository<BillAction, Long> { + + @EntityGraph(attributePaths = {"action"}) + List<BillAction> findByAction_Event(Event event); + + void deleteByAction_EventAndActionId(Event event, Long actionId); + + Optional<BillAction> findByAction_Id(Long actionId); + + @Query(""" + select ba + from BillAction ba + where ba.action.event = :event and ba.action.sequence > :sequence + """) + List<BillAction> findByEventAndGreaterThanSequence(Event event, Long sequence); +} diff --git a/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java b/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java new file mode 100644 index 000000000..ba380aae5 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java @@ -0,0 +1,81 @@ +package server.haengdong.domain.action; + +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +public class CurrentMembers { + + private final Set<String> members; + + public CurrentMembers() { + this(new HashSet<>()); + } + + protected CurrentMembers(Set<String> members) { + this.members = members; + } + + public static CurrentMembers of(List<MemberAction> memberActions) { + List<MemberAction> sortedMemberActions = getSortedMemberActions(memberActions); + Set<String> members = new HashSet<>(); + for (MemberAction memberAction : sortedMemberActions) { + String member = memberAction.getMemberName(); + if (memberAction.isSameStatus(MemberActionStatus.IN)) { + members.add(member); + continue; + } + members.remove(member); + } + + return new CurrentMembers(members); + } + + private static List<MemberAction> getSortedMemberActions(List<MemberAction> memberActions) { + return memberActions.stream() + .sorted(Comparator.comparing(MemberAction::getSequence)) + .toList(); + } + + public CurrentMembers addMemberAction(MemberAction memberAction) { + String memberName = memberAction.getMemberName(); + + Set<String> currentMembers = new HashSet<>(members); + + if (memberAction.isIn()) { + currentMembers.add(memberName); + } else { + currentMembers.remove(memberName); + } + return new CurrentMembers(currentMembers); + } + + public void validate(String memberName, MemberActionStatus memberActionStatus) { + if (memberActionStatus == MemberActionStatus.IN && members.contains(memberName)) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_ALREADY_EXIST); + } + if (memberActionStatus == MemberActionStatus.OUT && !members.contains(memberName)) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_NOT_EXIST); + } + } + + public boolean isEmpty() { + return members.isEmpty(); + } + + public boolean isNotEmpty() { + return !members.isEmpty(); + } + + public int size() { + return members.size(); + } + + public Set<String> getMembers() { + return Collections.unmodifiableSet(members); + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberAction.java b/server/src/main/java/server/haengdong/domain/action/MemberAction.java new file mode 100644 index 000000000..3faf65bde --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/MemberAction.java @@ -0,0 +1,76 @@ +package server.haengdong.domain.action; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToOne; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class MemberAction implements Comparable<MemberAction> { + + public static final int MIN_NAME_LENGTH = 1; + public static final int MAX_NAME_LENGTH = 4; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) + private Action action; + + private String memberName; + + @Enumerated(EnumType.STRING) + private MemberActionStatus status; + + private Long memberGroupId; + + public MemberAction(Action action, String memberName, MemberActionStatus status, Long memberGroupId) { + validateMemberName(memberName); + this.action = action; + this.memberName = memberName; + this.status = status; + this.memberGroupId = memberGroupId; + } + + private void validateMemberName(String memberName) { + int memberLength = memberName.length(); + if (memberLength < MIN_NAME_LENGTH || memberLength > MAX_NAME_LENGTH) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_LENGTH_INVALID); + } + } + + public void updateMemberName(String memberName) { + validateMemberName(memberName); + this.memberName = memberName; + } + + public boolean isIn() { + return status == MemberActionStatus.IN; + } + + public boolean isSameStatus(MemberActionStatus memberActionStatus) { + return status == memberActionStatus; + } + + public Long getSequence() { + return action.getSequence(); + } + + @Override + public int compareTo(MemberAction o) { + return Long.compare(this.getSequence(), o.getSequence()); + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java b/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java new file mode 100644 index 000000000..324ff9797 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java @@ -0,0 +1,53 @@ +package server.haengdong.domain.action; + +import java.util.List; +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; +import server.haengdong.domain.event.Event; + +@Repository +public interface MemberActionRepository extends JpaRepository<MemberAction, Long> { + + @Query("select m from MemberAction m join fetch m.action where m.action.event = :event") + List<MemberAction> findAllByEvent(@Param("event") Event event); + + @Query(""" + select distinct m.memberName + from MemberAction m + where m.action.event = :event + """) + List<String> findAllUniqueMemberByEvent(Event event); + + @Modifying + @Query(""" + delete + from MemberAction m + where m.memberName = :memberName and m.action.event = :event + """) + void deleteAllByEventAndMemberName(Event event, String memberName); + + Optional<MemberAction> findByAction(Action action); + + @Modifying + @Query(""" + delete + from MemberAction m + where m.memberName = :memberName and m.action.sequence >= :sequence + """) + void deleteAllByMemberNameAndMinSequence(String memberName, Long sequence); + + List<MemberAction> findAllByAction_EventAndMemberName(Event event, String memberName); + + boolean existsByAction_EventAndMemberName(Event event, String updatedMemberName); + + @Query(""" + select ma + from MemberAction ma + where ma.action.event = :event and ma.action.sequence < :sequence + """) + List<MemberAction> findByEventAndSequence(Event event, Long sequence); +} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java b/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java new file mode 100644 index 000000000..76c5a66d4 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java @@ -0,0 +1,19 @@ +package server.haengdong.domain.action; + +import java.util.Arrays; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +public enum MemberActionStatus { + IN, + OUT, + ; + + public static MemberActionStatus of(String status) { + return Arrays.stream(MemberActionStatus.values()) + .filter(s -> s.name().equals(status)) + .findFirst() + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.MEMBER_ACTION_STATUS_INVALID, + String.format(HaengdongErrorCode.MEMBER_ACTION_STATUS_INVALID.getMessage(), status))); + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java b/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java new file mode 100644 index 000000000..7a707b9d8 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java @@ -0,0 +1,75 @@ +package server.haengdong.domain.action; + +import static java.util.stream.Collectors.toMap; + +import java.util.List; +import java.util.Map; +import java.util.PriorityQueue; +import java.util.function.Function; +import lombok.Getter; + +@Getter +public class MemberBillReport { + + private final Map<String, Long> reports; + + private MemberBillReport(Map<String, Long> reports) { + this.reports = reports; + } + + public static MemberBillReport createByActions(List<BillAction> billActions, List<MemberAction> memberActions) { + PriorityQueue<BillAction> sortedBillActions = new PriorityQueue<>(billActions); + PriorityQueue<MemberAction> sortedMemberActions = new PriorityQueue<>(memberActions); + + Map<String, Long> memberBillReports = initReports(memberActions); + CurrentMembers currentMembers = new CurrentMembers(); + while (!sortedBillActions.isEmpty() && !sortedMemberActions.isEmpty()) { + if (isMemberActionTurn(sortedMemberActions, sortedBillActions)) { + MemberAction memberAction = sortedMemberActions.poll(); + currentMembers = currentMembers.addMemberAction(memberAction); + continue; + } + addBillAction(sortedBillActions, currentMembers, memberBillReports); + } + + while (!sortedBillActions.isEmpty()) { + addBillAction(sortedBillActions, currentMembers, memberBillReports); + } + + return new MemberBillReport(memberBillReports); + } + + private static Map<String, Long> initReports(List<MemberAction> memberActions) { + return memberActions.stream() + .map(MemberAction::getMemberName) + .distinct() + .collect(toMap(Function.identity(), i -> 0L)); + } + + private static boolean isMemberActionTurn( + PriorityQueue<MemberAction> memberActions, + PriorityQueue<BillAction> billActions + ) { + MemberAction memberAction = memberActions.peek(); + BillAction billAction = billActions.peek(); + + return memberAction.getSequence() < billAction.getSequence(); + } + + private static void addBillAction( + PriorityQueue<BillAction> sortedBillActions, + CurrentMembers currentMembers, + Map<String, Long> memberBillReports + ) { + BillAction billAction = sortedBillActions.poll(); + if (currentMembers.isEmpty()) { + return; + } + + for (String currentMember : currentMembers.getMembers()) { + Long currentPrice = billAction.findPriceByMemberName(currentMember); + Long price = memberBillReports.get(currentMember) + currentPrice; + memberBillReports.put(currentMember, price); + } + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java b/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java new file mode 100644 index 000000000..9e32bd733 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java @@ -0,0 +1,11 @@ +package server.haengdong.domain.action; + +import org.springframework.stereotype.Component; + +@Component +public class MemberGroupIdProvider { + + public Long createGroupId() { + return System.currentTimeMillis(); + } +} diff --git a/server/src/main/java/server/haengdong/domain/event/Event.java b/server/src/main/java/server/haengdong/domain/event/Event.java new file mode 100644 index 000000000..bb5d53dbc --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/event/Event.java @@ -0,0 +1,70 @@ +package server.haengdong.domain.event; + +import jakarta.persistence.AttributeOverride; +import jakarta.persistence.Column; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class Event { + + public static final int MIN_NAME_LENGTH = 1; + public static final int MAX_NAME_LENGTH = 20; + private static final String SPACES = " "; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + + @Embedded + @AttributeOverride(name = "value", column = @Column(name = "password")) + private Password password; + + private String token; + + public Event(String name, String password, String token) { + validateName(name); + this.name = name; + this.password = new Password(password); + this.token = token; + } + + private void validateName(String name) { + int nameLength = name.trim().length(); + if (nameLength < MIN_NAME_LENGTH || MAX_NAME_LENGTH < nameLength) { + throw new HaengdongException(HaengdongErrorCode.EVENT_NAME_LENGTH_INVALID, + String.format("ํ–‰์‚ฌ ์ด๋ฆ„์€ %d์ž ์ด์ƒ %d์ž ์ดํ•˜๋งŒ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ž…๋ ฅํ•œ ์ด๋ฆ„ ๊ธธ์ด : %d", + MIN_NAME_LENGTH, + MAX_NAME_LENGTH, + name.length())); + } + if (isBlankContinuous(name)) { + throw new HaengdongException(HaengdongErrorCode.EVENT_NAME_CONSECUTIVE_SPACES, + String.format("ํ–‰์‚ฌ ์ด๋ฆ„์—๋Š” ๊ณต๋ฐฑ ๋ฌธ์ž๊ฐ€ ์—ฐ์†๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ž…๋ ฅํ•œ ์ด๋ฆ„ : %s", name)); + } + } + + private boolean isBlankContinuous(String name) { + return name.contains(SPACES); + } + + public boolean isTokenMismatch(String token) { + return !this.token.equals(token); + } + + public boolean isPasswordMismatch(String rawPassword) { + return !password.matches(rawPassword); + } +} diff --git a/server/src/main/java/server/haengdong/domain/event/EventRepository.java b/server/src/main/java/server/haengdong/domain/event/EventRepository.java new file mode 100644 index 000000000..09526125e --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/event/EventRepository.java @@ -0,0 +1,11 @@ +package server.haengdong.domain.event; + +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface EventRepository extends JpaRepository<Event, Long> { + + Optional<Event> findByToken(String token); +} diff --git a/server/src/main/java/server/haengdong/domain/event/EventStep.java b/server/src/main/java/server/haengdong/domain/event/EventStep.java new file mode 100644 index 000000000..297abdb66 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/event/EventStep.java @@ -0,0 +1,28 @@ +package server.haengdong.domain.event; + +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class EventStep { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + private Event event; + + private String name; + + private Long sequence; +} diff --git a/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java b/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java new file mode 100644 index 000000000..6450f0dcf --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java @@ -0,0 +1,12 @@ +package server.haengdong.domain.event; + +import java.util.UUID; +import org.springframework.stereotype.Component; + +@Component +public class EventTokenProvider { + + public String createToken() { + return UUID.randomUUID().toString(); + } +} diff --git a/server/src/main/java/server/haengdong/domain/event/Password.java b/server/src/main/java/server/haengdong/domain/event/Password.java new file mode 100644 index 000000000..375849dbf --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/event/Password.java @@ -0,0 +1,52 @@ +package server.haengdong.domain.event; + +import jakarta.persistence.Embeddable; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@Embeddable +public class Password { + + public static final int PASSWORD_LENGTH = 4; + private static final Pattern PASSWORD_PATTERN = Pattern.compile(String.format("^\\d{%d}$", PASSWORD_LENGTH)); + private static final String HASH_ALGORITHM = "SHA-256"; + + private String value; + + public Password(String password) { + validatePassword(password); + this.value = encode(password); + } + + private void validatePassword(String password) { + Matcher matcher = PASSWORD_PATTERN.matcher(password); + if (!matcher.matches()) { + throw new HaengdongException(HaengdongErrorCode.EVENT_PASSWORD_FORMAT_INVALID); + } + } + + private String encode(String rawPassword) { + try { + MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM); + byte[] hashedPassword = digest.digest(rawPassword.getBytes()); + return Base64.getEncoder().encodeToString(hashedPassword); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException("ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."); + } + } + + public boolean matches(String rawPassword) { + String hashedPassword = encode(rawPassword); + return value.equals(hashedPassword); + } +} diff --git a/server/src/main/java/server/haengdong/exception/AuthenticationException.java b/server/src/main/java/server/haengdong/exception/AuthenticationException.java new file mode 100644 index 000000000..2efcb16e7 --- /dev/null +++ b/server/src/main/java/server/haengdong/exception/AuthenticationException.java @@ -0,0 +1,19 @@ +package server.haengdong.exception; + +import lombok.Getter; + +@Getter +public class AuthenticationException extends RuntimeException { + + private final HaengdongErrorCode errorCode; + private final String message; + + public AuthenticationException(HaengdongErrorCode errorCode) { + this(errorCode, errorCode.getMessage()); + } + + public AuthenticationException(HaengdongErrorCode errorCode, String message) { + this.errorCode = errorCode; + this.message = message; + } +} diff --git a/server/src/main/java/server/haengdong/exception/ErrorResponse.java b/server/src/main/java/server/haengdong/exception/ErrorResponse.java new file mode 100644 index 000000000..d0a2b01a0 --- /dev/null +++ b/server/src/main/java/server/haengdong/exception/ErrorResponse.java @@ -0,0 +1,15 @@ +package server.haengdong.exception; + +public record ErrorResponse( + HaengdongErrorCode errorCode, + String message +) { + + public static ErrorResponse of(HaengdongErrorCode errorCode) { + return new ErrorResponse(errorCode, errorCode.getMessage()); + } + + public static ErrorResponse of(HaengdongErrorCode errorCode, String message) { + return new ErrorResponse(errorCode, message); + } +} diff --git a/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java b/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java new file mode 100644 index 000000000..0cee7cb4c --- /dev/null +++ b/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java @@ -0,0 +1,90 @@ +package server.haengdong.exception; + +import jakarta.servlet.http.HttpServletRequest; +import java.io.BufferedReader; +import java.io.IOException; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.resource.NoResourceFoundException; + +@Slf4j +@RestControllerAdvice +public class GlobalExceptionHandler { + + private static final String LOG_FORMAT = """ + \n\t{ + "RequestURI": "{} {}", + "RequestBody": {}, + "ErrorMessage": "{}" + \t} + """; + + @ExceptionHandler(AuthenticationException.class) + public ResponseEntity<ErrorResponse> authenticationException(HttpServletRequest req, AuthenticationException e) { + log.warn(LOG_FORMAT, req.getMethod(), req.getRequestURI(), getRequestBody(req), e.getMessage(), e); + return ResponseEntity.status(HttpStatus.UNAUTHORIZED) + .body(ErrorResponse.of(e.getErrorCode())); + } + + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public ResponseEntity<ErrorResponse> noResourceException(HttpRequestMethodNotSupportedException e) { + log.warn(e.getMessage(), e); + return ResponseEntity.badRequest() + .body(ErrorResponse.of(HaengdongErrorCode.REQUEST_METHOD_NOT_SUPPORTED)); + } + + @ExceptionHandler(NoResourceFoundException.class) + public ResponseEntity<ErrorResponse> noResourceException(NoResourceFoundException e) { + log.warn(e.getMessage(), e); + return ResponseEntity.badRequest() + .body(ErrorResponse.of(HaengdongErrorCode.NO_RESOURCE_REQUEST)); + } + + @ExceptionHandler(HttpMessageNotReadableException.class) + public ResponseEntity<ErrorResponse> httpMessageNotReadableException(HttpMessageNotReadableException e) { + log.warn(e.getMessage(), e); + return ResponseEntity.badRequest() + .body(ErrorResponse.of(HaengdongErrorCode.MESSAGE_NOT_READABLE)); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity<ErrorResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { + log.warn(e.getMessage(), e); + String errorMessage = e.getFieldErrors().stream() + .map(error -> error.getField() + " " + error.getDefaultMessage()) + .collect(Collectors.joining(", ")); + + return ResponseEntity.badRequest() + .body(ErrorResponse.of(HaengdongErrorCode.REQUEST_EMPTY, errorMessage)); + } + + @ExceptionHandler(HaengdongException.class) + public ResponseEntity<ErrorResponse> haengdongException(HttpServletRequest req, HaengdongException e) { + log.warn(LOG_FORMAT, req.getMethod(), req.getRequestURI(), getRequestBody(req), e.getMessage(), e); + return ResponseEntity.badRequest() + .body(ErrorResponse.of(e.getErrorCode())); + } + + @ExceptionHandler(Exception.class) + public ResponseEntity<ErrorResponse> handleException(HttpServletRequest req, Exception e) { + log.error(LOG_FORMAT, req.getMethod(), req.getRequestURI(), getRequestBody(req), e.getMessage(), e); + return ResponseEntity.internalServerError() + .body(ErrorResponse.of(HaengdongErrorCode.INTERNAL_SERVER_ERROR)); + } + + private String getRequestBody(HttpServletRequest req) { + try (BufferedReader reader = req.getReader()) { + return reader.lines().collect(Collectors.joining(System.lineSeparator() + "\t")); + } catch (IOException e) { + log.error("Failed to read request body", e); + return ""; + } + } +} diff --git a/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java b/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java new file mode 100644 index 000000000..475d16c11 --- /dev/null +++ b/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java @@ -0,0 +1,69 @@ +package server.haengdong.exception; + +import lombok.Getter; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.Password; + +@Getter +public enum HaengdongErrorCode { + + /* Domain */ + + EVENT_NOT_FOUND("์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค."), + EVENT_NAME_LENGTH_INVALID(String.format("ํ–‰์‚ฌ ์ด๋ฆ„์€ %d์ž ์ด์ƒ %d์ž ์ดํ•˜๋งŒ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.", + Event.MIN_NAME_LENGTH, + Event.MAX_NAME_LENGTH)), + EVENT_NAME_CONSECUTIVE_SPACES("ํ–‰์‚ฌ ์ด๋ฆ„์—๋Š” ๊ณต๋ฐฑ ๋ฌธ์ž๊ฐ€ ์—ฐ์†๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ž…๋ ฅํ•œ ์ด๋ฆ„ : %s"), + EVENT_PASSWORD_FORMAT_INVALID(String.format("๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” %d์ž๋ฆฌ ์ˆซ์ž๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.", Password.PASSWORD_LENGTH)), + + ACTION_NOT_FOUND("์กด์žฌํ•˜์ง€ ์•Š๋Š” ์•ก์…˜์ž…๋‹ˆ๋‹ค."), + + MEMBER_NAME_LENGTH_INVALID(String.format("๋ฉค๋ฒ„ ์ด๋ฆ„์€ %d์ž ์ด์ƒ %d์ž ์ดํ•˜๋งŒ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.", + MemberAction.MIN_NAME_LENGTH, + MemberAction.MAX_NAME_LENGTH)), + MEMBER_NAME_DUPLICATE("์ค‘๋ณต๋œ ํ–‰์‚ฌ ์ฐธ์—ฌ ์ธ์› ์ด๋ฆ„์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค."), + MEMBER_NOT_EXIST("ํ˜„์žฌ ์ฐธ์—ฌํ•˜๊ณ  ์žˆ์ง€ ์•Š๋Š” ์ธ์›์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค."), + MEMBER_ALREADY_EXIST("ํ˜„์žฌ ์ฐธ์—ฌํ•˜๊ณ  ์žˆ๋Š” ์ธ์›์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค."), + MEMBER_NAME_CHANGE_DUPLICATE("์ค‘๋ณต๋œ ์ฐธ์—ฌ ์ธ์› ์ด๋ฆ„ ๋ณ€๊ฒฝ ์š”์ฒญ์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค."), + + MEMBER_ACTION_NOT_FOUND("์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ฉค๋ฒ„ ์•ก์…˜์ž…๋‹ˆ๋‹ค."), + MEMBER_ACTION_STATUS_INVALID("๋ฉค๋ฒ„ ์•ก์…˜์€ IN, OUT๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ž…๋ ฅํ•œ ๋ฉค๋ฒ„ ์•ก์…˜: %s"), + + BILL_ACTION_NOT_FOUND("์กด์žฌํ•˜์ง€ ์•Š๋Š” ์ง€์ถœ ์•ก์…˜์ž…๋‹ˆ๋‹ค."), + BILL_ACTION_TITLE_INVALID(String.format("์•ž๋’ค ๊ณต๋ฐฑ์„ ์ œ๊ฑฐํ•œ ์ง€์ถœ ๋‚ด์—ญ ์ œ๋ชฉ์€ %d ~ %d์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.", + BillAction.MIN_TITLE_LENGTH, + BillAction.MAX_TITLE_LENGTH)), + BILL_ACTION_PRICE_INVALID(String.format("์ง€์ถœ ๊ธˆ์•ก์€ %,d ์ดํ•˜์˜ ์ž์—ฐ์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.", BillAction.MAX_PRICE)), + BILL_ACTION_DETAIL_NOT_FOUND("์กด์žฌํ•˜์ง€ ์•Š๋Š” ์ฐธ์—ฌ์ž ์ง€์ถœ์ž…๋‹ˆ๋‹ค."), + BILL_ACTION_PRICE_NOT_MATCHED("์ง€์ถœ ์ด์•ก์ด ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."), + + /* Authentication */ + + PASSWORD_INVALID("๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."), + + TOKEN_NOT_FOUND("ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."), + TOKEN_EXPIRED("๋งŒ๋ฃŒ๋œ ํ† ํฐ์ž…๋‹ˆ๋‹ค."), + TOKEN_INVALID("์œ ํšจํ•˜์ง€ ์•Š์€ ํ† ํฐ์ž…๋‹ˆ๋‹ค."), + + FORBIDDEN("์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ํ–‰์‚ฌ์ž…๋‹ˆ๋‹ค."), + + /* Request Validation */ + + REQUEST_EMPTY("์ž…๋ ฅ ๊ฐ’์€ ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + + /* System */, + + MESSAGE_NOT_READABLE("์ฝ์„ ์ˆ˜ ์—†๋Š” ์š”์ฒญ์ž…๋‹ˆ๋‹ค."), + REQUEST_METHOD_NOT_SUPPORTED("์ง€์›ํ•˜์ง€ ์•Š๋Š” ์š”์ฒญ ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค."), + NO_RESOURCE_REQUEST("์กด์žฌํ•˜์ง€ ์•Š๋Š” ์ž์›์ž…๋‹ˆ๋‹ค."), + INTERNAL_SERVER_ERROR("์„œ๋ฒ„ ๋‚ด๋ถ€์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค."), + ; + + private final String message; + + HaengdongErrorCode(String message) { + this.message = message; + } +} diff --git a/server/src/main/java/server/haengdong/exception/HaengdongException.java b/server/src/main/java/server/haengdong/exception/HaengdongException.java new file mode 100644 index 000000000..b86fe4ffc --- /dev/null +++ b/server/src/main/java/server/haengdong/exception/HaengdongException.java @@ -0,0 +1,19 @@ +package server.haengdong.exception; + +import lombok.Getter; + +@Getter +public class HaengdongException extends RuntimeException { + + private final HaengdongErrorCode errorCode; + private final String message; + + public HaengdongException(HaengdongErrorCode errorCode) { + this(errorCode, errorCode.getMessage()); + } + + public HaengdongException(HaengdongErrorCode errorCode, String message) { + this.errorCode = errorCode; + this.message = message; + } +} diff --git a/server/src/main/java/server/haengdong/infrastructure/auth/AuthenticationExtractor.java b/server/src/main/java/server/haengdong/infrastructure/auth/AuthenticationExtractor.java new file mode 100644 index 000000000..4972de48a --- /dev/null +++ b/server/src/main/java/server/haengdong/infrastructure/auth/AuthenticationExtractor.java @@ -0,0 +1,23 @@ +package server.haengdong.infrastructure.auth; + +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import java.util.Arrays; +import server.haengdong.exception.AuthenticationException; +import server.haengdong.exception.HaengdongErrorCode; + +public class AuthenticationExtractor { + + public String extract(HttpServletRequest request, String cookieName) { + Cookie[] cookies = request.getCookies(); + if (cookies == null) { + throw new AuthenticationException(HaengdongErrorCode.TOKEN_NOT_FOUND); + } + + return Arrays.stream(cookies) + .filter(cookie -> cookieName.equals(cookie.getName())) + .findFirst() + .orElseThrow(() -> new AuthenticationException(HaengdongErrorCode.TOKEN_NOT_FOUND)) + .getValue(); + } +} diff --git a/server/src/main/java/server/haengdong/infrastructure/auth/CookieProperties.java b/server/src/main/java/server/haengdong/infrastructure/auth/CookieProperties.java new file mode 100644 index 000000000..18f867601 --- /dev/null +++ b/server/src/main/java/server/haengdong/infrastructure/auth/CookieProperties.java @@ -0,0 +1,15 @@ +package server.haengdong.infrastructure.auth; + +import java.time.Duration; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties("cookie") +public record CookieProperties( + boolean httpOnly, + boolean secure, + String domain, + String path, + String sameSite, + Duration maxAge +) { +} diff --git a/server/src/main/java/server/haengdong/infrastructure/auth/JwtTokenProvider.java b/server/src/main/java/server/haengdong/infrastructure/auth/JwtTokenProvider.java new file mode 100644 index 000000000..df9ec6a81 --- /dev/null +++ b/server/src/main/java/server/haengdong/infrastructure/auth/JwtTokenProvider.java @@ -0,0 +1,54 @@ +package server.haengdong.infrastructure.auth; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jws; +import io.jsonwebtoken.JwtException; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import server.haengdong.domain.TokenProvider; + +public class JwtTokenProvider implements TokenProvider { + + private final TokenProperties tokenProperties; + + public JwtTokenProvider(TokenProperties tokenProperties) { + this.tokenProperties = tokenProperties; + } + + @Override + public String createToken(Map<String, Object> payload) { + Claims claims = Jwts.claims(new HashMap<>(payload)); + Date now = new Date(); + Date validity = new Date(now.getTime() + tokenProperties.expireLength()); + + return Jwts.builder() + .setClaims(claims) + .setIssuedAt(now) + .setExpiration(validity) + .signWith(SignatureAlgorithm.HS256, tokenProperties.secretKey()) + .compact(); + } + + @Override + public Map<String, Object> getPayload(String token) { + return Jwts.parser() + .setSigningKey(tokenProperties.secretKey()) + .parseClaimsJws(token) + .getBody(); + } + + @Override + public boolean validateToken(String token) { + try { + Jws<Claims> claims = Jwts.parser().setSigningKey(tokenProperties.secretKey()).parseClaimsJws(token); + + return !claims.getBody().getExpiration().before(new Date()); + } catch (JwtException | IllegalArgumentException e) { + return false; + } + } +} + diff --git a/server/src/main/java/server/haengdong/infrastructure/auth/TokenProperties.java b/server/src/main/java/server/haengdong/infrastructure/auth/TokenProperties.java new file mode 100644 index 000000000..11dedcdbf --- /dev/null +++ b/server/src/main/java/server/haengdong/infrastructure/auth/TokenProperties.java @@ -0,0 +1,7 @@ +package server.haengdong.infrastructure.auth; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties("security.jwt.token") +public record TokenProperties(String secretKey, Long expireLength) { +} diff --git a/server/src/main/java/server/haengdong/presentation/ActionController.java b/server/src/main/java/server/haengdong/presentation/ActionController.java new file mode 100644 index 000000000..657cb567e --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/ActionController.java @@ -0,0 +1,26 @@ +package server.haengdong.presentation; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; +import server.haengdong.application.ActionService; +import server.haengdong.application.response.MemberBillReportAppResponse; +import server.haengdong.presentation.response.MemberBillReportsResponse; + +@RequiredArgsConstructor +@RestController +public class ActionController { + + private final ActionService actionService; + + @GetMapping("/api/events/{eventId}/actions/reports") + public ResponseEntity<MemberBillReportsResponse> getMemberBillReports(@PathVariable("eventId") String token) { + List<MemberBillReportAppResponse> memberBillReports = actionService.getMemberBillReports(token); + + return ResponseEntity.ok() + .body(MemberBillReportsResponse.of(memberBillReports)); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/BillActionController.java b/server/src/main/java/server/haengdong/presentation/BillActionController.java new file mode 100644 index 000000000..56e99337d --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/BillActionController.java @@ -0,0 +1,55 @@ +package server.haengdong.presentation; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import server.haengdong.application.BillActionService; +import server.haengdong.presentation.request.BillActionUpdateRequest; +import server.haengdong.presentation.request.BillActionsSaveRequest; + +@RequiredArgsConstructor +@RestController +public class BillActionController { + + private final BillActionService billActionService; + + @PostMapping("/api/events/{eventId}/bill-actions") + public ResponseEntity<Void> saveAllBillAction( + @PathVariable("eventId") String token, + @Valid @RequestBody BillActionsSaveRequest request + ) { + billActionService.saveAllBillAction(token, request.toAppRequests()); + + return ResponseEntity.ok() + .build(); + } + + @PutMapping("/api/events/{eventId}/bill-actions/{actionId}") + public ResponseEntity<Void> updateBillAction( + @PathVariable("eventId") String token, + @PathVariable("actionId") Long actionId, + @Valid @RequestBody BillActionUpdateRequest request + ) { + billActionService.updateBillAction(token, actionId, request.toAppResponse()); + + return ResponseEntity.ok() + .build(); + } + + @DeleteMapping("/api/events/{eventId}/bill-actions/{actionId}") + public ResponseEntity<Void> deleteBillAction( + @PathVariable("eventId") String token, + @PathVariable("actionId") Long actionId + ) { + billActionService.deleteBillAction(token, actionId); + + return ResponseEntity.ok() + .build(); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/BillActionDetailController.java b/server/src/main/java/server/haengdong/presentation/BillActionDetailController.java new file mode 100644 index 000000000..5602e6777 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/BillActionDetailController.java @@ -0,0 +1,42 @@ +package server.haengdong.presentation; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import server.haengdong.application.BillActionDetailService; +import server.haengdong.application.response.BillActionDetailsAppResponse; +import server.haengdong.presentation.request.BillActionDetailsUpdateRequest; +import server.haengdong.presentation.response.BillActionDetailsResponse; + +@RequiredArgsConstructor +@RestController +public class BillActionDetailController { + + private final BillActionDetailService billActionDetailService; + + @GetMapping("/api/events/{eventId}/bill-actions/{actionId}/fixed") + public ResponseEntity<BillActionDetailsResponse> findBillActionDetails( + @PathVariable("eventId") String token, + @PathVariable("actionId") Long actionId + ) { + BillActionDetailsAppResponse appResponse = billActionDetailService.findBillActionDetails(token, actionId); + + return ResponseEntity.ok(BillActionDetailsResponse.of(appResponse)); + } + + @PutMapping("/api/events/{eventId}/bill-actions/{actionId}/fixed") + public ResponseEntity<Void> updateBillActionDetails( + @PathVariable("eventId") String token, + @PathVariable("actionId") Long actionId, + @Valid @RequestBody BillActionDetailsUpdateRequest request + ) { + billActionDetailService.updateBillActionDetails(token, actionId, request.toAppRequest()); + + return ResponseEntity.ok().build(); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/EventController.java b/server/src/main/java/server/haengdong/presentation/EventController.java new file mode 100644 index 000000000..34261042f --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/EventController.java @@ -0,0 +1,120 @@ +package server.haengdong.presentation; + +import jakarta.validation.Valid; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseCookie; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import server.haengdong.application.AuthService; +import server.haengdong.application.EventService; +import server.haengdong.application.response.ActionAppResponse; +import server.haengdong.infrastructure.auth.CookieProperties; +import server.haengdong.presentation.request.EventLoginRequest; +import server.haengdong.presentation.request.EventSaveRequest; +import server.haengdong.presentation.request.MemberNamesUpdateRequest; +import server.haengdong.presentation.response.ActionsResponse; +import server.haengdong.presentation.response.EventDetailResponse; +import server.haengdong.presentation.response.EventResponse; +import server.haengdong.presentation.response.MembersResponse; +import server.haengdong.presentation.response.StepsResponse; + +@Slf4j +@RequiredArgsConstructor +@EnableConfigurationProperties(CookieProperties.class) +@RestController +public class EventController { + + private final EventService eventService; + private final AuthService authService; + private final CookieProperties cookieProperties; + + @PostMapping("/api/events") + public ResponseEntity<EventResponse> saveEvent(@Valid @RequestBody EventSaveRequest request) { + EventResponse eventResponse = EventResponse.of(eventService.saveEvent(request.toAppRequest())); + + String jwtToken = authService.createToken(eventResponse.eventId()); + + ResponseCookie responseCookie = createResponseCookie(jwtToken); + return ResponseEntity.ok() + .header(HttpHeaders.SET_COOKIE, responseCookie.toString()) + .body(eventResponse); + } + + @GetMapping("/api/events/{eventId}") + public ResponseEntity<EventDetailResponse> findEvent(@PathVariable("eventId") String token) { + EventDetailResponse eventDetailResponse = EventDetailResponse.of(eventService.findEvent(token)); + + return ResponseEntity.ok(eventDetailResponse); + } + + @GetMapping("/api/events/{eventId}/actions") + public ResponseEntity<StepsResponse> findActions(@PathVariable("eventId") String token) { + StepsResponse stepsResponse = StepsResponse.of(eventService.findActions(token)); + + return ResponseEntity.ok(stepsResponse); + } + + @GetMapping("/api/events/{eventId}/actions/v2") + public ResponseEntity<ActionsResponse> findActions2(@PathVariable("eventId") String token) { + List<ActionAppResponse> actions = eventService.findActions(token); + ActionsResponse actionsResponse = ActionsResponse.of(actions); + + return ResponseEntity.ok(actionsResponse); + } + + @GetMapping("/api/events/{eventId}/members") + public ResponseEntity<MembersResponse> findAllMembers(@PathVariable("eventId") String token) { + MembersResponse response = MembersResponse.of(eventService.findAllMembers(token)); + + return ResponseEntity.ok(response); + } + + @PutMapping("/api/events/{eventId}/members/nameChange") + public ResponseEntity<Void> updateMember( + @PathVariable("eventId") String token, + @Valid @RequestBody MemberNamesUpdateRequest request + ) { + eventService.updateMember(token, request.toAppRequest()); + + return ResponseEntity.ok().build(); + } + + @PostMapping("/api/events/{eventId}/login") + public ResponseEntity<Void> loginEvent( + @PathVariable("eventId") String token, + @Valid @RequestBody EventLoginRequest request + ) { + eventService.validatePassword(request.toAppRequest(token)); + String jwtToken = authService.createToken(token); + + ResponseCookie responseCookie = createResponseCookie(jwtToken); + return ResponseEntity.ok() + .header(HttpHeaders.SET_COOKIE, responseCookie.toString()) + .build(); + } + + @PostMapping("/api/events/{eventId}/auth") + public ResponseEntity<Void> authenticate(@PathVariable("eventId") String token) { + return ResponseEntity.ok().build(); + } + + private ResponseCookie createResponseCookie(String token) { + return ResponseCookie.from(authService.getTokenName(), token) + .httpOnly(cookieProperties.httpOnly()) + .secure(cookieProperties.secure()) + .domain(cookieProperties.domain()) + .path(cookieProperties.path()) + .sameSite(cookieProperties.sameSite()) + .maxAge(cookieProperties.maxAge()) + .build(); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/MemberActionController.java b/server/src/main/java/server/haengdong/presentation/MemberActionController.java new file mode 100644 index 000000000..1703245f7 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/MemberActionController.java @@ -0,0 +1,60 @@ +package server.haengdong.presentation; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import server.haengdong.application.MemberActionService; +import server.haengdong.application.response.CurrentMemberAppResponse; +import server.haengdong.presentation.request.MemberActionsSaveRequest; +import server.haengdong.presentation.response.CurrentMembersResponse; + +@RequiredArgsConstructor +@RestController +public class MemberActionController { + + private final MemberActionService memberActionService; + + @PostMapping("/api/events/{eventId}/member-actions") + public ResponseEntity<Void> saveMemberAction( + @PathVariable("eventId") String token, + @RequestBody MemberActionsSaveRequest request + ) { + memberActionService.saveMemberAction(token, request.toAppRequest()); + + return ResponseEntity.ok().build(); + } + + @GetMapping("/api/events/{eventId}/members/current") + public ResponseEntity<CurrentMembersResponse> getCurrentMembers(@PathVariable("eventId") String token) { + List<CurrentMemberAppResponse> currentMembers = memberActionService.getCurrentMembers(token); + + return ResponseEntity.ok() + .body(CurrentMembersResponse.of(currentMembers)); + } + + @DeleteMapping("/api/events/{eventId}/members/{memberName}") + public ResponseEntity<Void> deleteMember( + @PathVariable("eventId") String token, + @PathVariable("memberName") String memberName + ) { + memberActionService.deleteMember(token, memberName); + + return ResponseEntity.ok().build(); + } + + @DeleteMapping("/api/events/{eventId}/member-actions/{actionId}") + public ResponseEntity<Void> deleteMemberAction( + @PathVariable("eventId") String token, + @PathVariable("actionId") Long actionId + ) { + memberActionService.deleteMemberAction(token, actionId); + + return ResponseEntity.ok().build(); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionDetailUpdateRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionDetailUpdateRequest.java new file mode 100644 index 000000000..21c4bd60f --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/BillActionDetailUpdateRequest.java @@ -0,0 +1,21 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import server.haengdong.application.request.BillActionDetailUpdateAppRequest; + +public record BillActionDetailUpdateRequest( + + @NotBlank(message = "๋งด๋ฒ„ ์ด๋ฆ„์€ ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + String name, + + @NotNull(message = "์ง€์ถœ ๊ธˆ์•ก์€ ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + Long price, + + @NotNull(message = "์ง€์ถœ ๊ธˆ์•ก์€ ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + boolean isFixed +) { + public BillActionDetailUpdateAppRequest toAppRequest() { + return new BillActionDetailUpdateAppRequest(this.name, this.price, this.isFixed); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionDetailsUpdateRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionDetailsUpdateRequest.java new file mode 100644 index 000000000..fafbb8fd7 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/BillActionDetailsUpdateRequest.java @@ -0,0 +1,16 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import java.util.List; +import server.haengdong.application.request.BillActionDetailsUpdateAppRequest; + +public record BillActionDetailsUpdateRequest( + @Valid @NotEmpty List<BillActionDetailUpdateRequest> members +) { + public BillActionDetailsUpdateAppRequest toAppRequest() { + return new BillActionDetailsUpdateAppRequest(members.stream() + .map(BillActionDetailUpdateRequest::toAppRequest) + .toList()); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java new file mode 100644 index 000000000..a47ff8316 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java @@ -0,0 +1,19 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import server.haengdong.application.request.BillActionAppRequest; + +public record BillActionSaveRequest( + + @NotBlank(message = "์ง€์ถœ ๋‚ด์—ญ ์ œ๋ชฉ์€ ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + String title, + + @NotNull(message = "์ง€์ถœ ๊ธˆ์•ก์€ ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + Long price +) { + + public BillActionAppRequest toAppRequest() { + return new BillActionAppRequest(title, price); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionUpdateRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionUpdateRequest.java new file mode 100644 index 000000000..680006816 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/BillActionUpdateRequest.java @@ -0,0 +1,18 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import server.haengdong.application.request.BillActionUpdateAppRequest; + +public record BillActionUpdateRequest( + + @NotBlank(message = "์ง€์ถœ ๋‚ด์—ญ ์ œ๋ชฉ์€ ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + String title, + + @NotNull(message = "์ง€์ถœ ๊ธˆ์•ก์€ ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + Long price +) { + public BillActionUpdateAppRequest toAppResponse() { + return new BillActionUpdateAppRequest(title, price); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java new file mode 100644 index 000000000..6727d4cf1 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java @@ -0,0 +1,18 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import java.util.List; +import server.haengdong.application.request.BillActionAppRequest; + +public record BillActionsSaveRequest( + + @Valid @NotEmpty List<BillActionSaveRequest> actions +) { + + public List<BillActionAppRequest> toAppRequests() { + return actions.stream() + .map(BillActionSaveRequest::toAppRequest) + .toList(); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/EventLoginRequest.java b/server/src/main/java/server/haengdong/presentation/request/EventLoginRequest.java new file mode 100644 index 000000000..a1286e903 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/EventLoginRequest.java @@ -0,0 +1,14 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.constraints.NotBlank; +import server.haengdong.application.request.EventLoginAppRequest; + +public record EventLoginRequest( + + @NotBlank(message = "๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + String password +) { + public EventLoginAppRequest toAppRequest(String token) { + return new EventLoginAppRequest(token, password); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java new file mode 100644 index 000000000..6bd7cd006 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java @@ -0,0 +1,18 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.constraints.NotBlank; +import server.haengdong.application.request.EventAppRequest; + +public record EventSaveRequest( + + @NotBlank(message = "ํ–‰์‚ฌ ์ด๋ฆ„์€ ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + String eventName, + + @NotBlank(message = "๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + String password +) { + + public EventAppRequest toAppRequest() { + return new EventAppRequest(eventName, password); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java new file mode 100644 index 000000000..41e95cc3c --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java @@ -0,0 +1,25 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import java.util.List; +import server.haengdong.application.request.MemberActionSaveAppRequest; +import server.haengdong.application.request.MemberActionsSaveAppRequest; + +public record MemberActionsSaveRequest( + + @NotEmpty + List<String> members, + + @NotBlank(message = "๋ฉค๋ฒ„ ์•ก์…˜์€ ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + String status +) { + + public MemberActionsSaveAppRequest toAppRequest() { + List<MemberActionSaveAppRequest> appRequests = members.stream() + .map(name -> new MemberActionSaveAppRequest(name, status)) + .toList(); + + return new MemberActionsSaveAppRequest(appRequests); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/MemberNameUpdateRequest.java b/server/src/main/java/server/haengdong/presentation/request/MemberNameUpdateRequest.java new file mode 100644 index 000000000..3cd2294ca --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/MemberNameUpdateRequest.java @@ -0,0 +1,18 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.constraints.NotBlank; +import server.haengdong.application.request.MemberNameUpdateAppRequest; + +public record MemberNameUpdateRequest( + + @NotBlank(message = "๋ฉค๋ฒ„ ์ด๋ฆ„์€ ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + String before, + + @NotBlank(message = "๋ฉค๋ฒ„ ์ด๋ฆ„์€ ๊ณต๋ฐฑ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + String after +) { + + public MemberNameUpdateAppRequest toAppRequest() { + return new MemberNameUpdateAppRequest(before, after); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/MemberNamesUpdateRequest.java b/server/src/main/java/server/haengdong/presentation/request/MemberNamesUpdateRequest.java new file mode 100644 index 000000000..872aa55de --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/MemberNamesUpdateRequest.java @@ -0,0 +1,17 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import java.util.List; +import server.haengdong.application.request.MemberNamesUpdateAppRequest; + +public record MemberNamesUpdateRequest( + @Valid @NotEmpty List<MemberNameUpdateRequest> members +) { + + public MemberNamesUpdateAppRequest toAppRequest() { + return new MemberNamesUpdateAppRequest(members.stream() + .map(MemberNameUpdateRequest::toAppRequest) + .toList()); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java b/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java new file mode 100644 index 000000000..ea26ea769 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java @@ -0,0 +1,26 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.ActionAppResponse; + +public record ActionResponse( + Long actionId, + String name, + Long price, + Long sequence, + boolean isFixed +) { + + public ActionResponse(Long actionId, String name, Long price, Long sequence) { + this(actionId, name, price, sequence, false); + } + + public static ActionResponse of(ActionAppResponse actionAppResponse) { + return new ActionResponse( + actionAppResponse.actionId(), + actionAppResponse.name(), + actionAppResponse.price(), + actionAppResponse.sequence(), + actionAppResponse.isFixed() + ); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/ActionResponse2.java b/server/src/main/java/server/haengdong/presentation/response/ActionResponse2.java new file mode 100644 index 000000000..ea46c5bd9 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/ActionResponse2.java @@ -0,0 +1,22 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.ActionAppResponse; + +public record ActionResponse2( + Long actionId, + String name, + Long price, + Long sequence, + String type +) { + + public static ActionResponse2 of(ActionAppResponse actionAppResponse) { + return new ActionResponse2( + actionAppResponse.actionId(), + actionAppResponse.name(), + actionAppResponse.price(), + actionAppResponse.sequence(), + actionAppResponse.actionType().name() + ); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java b/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java new file mode 100644 index 000000000..c8ae780e3 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java @@ -0,0 +1,14 @@ +package server.haengdong.presentation.response; + +import java.util.List; +import server.haengdong.application.response.ActionAppResponse; + +public record ActionsResponse( + List<ActionResponse2> actions +) { + public static ActionsResponse of(List<ActionAppResponse> actions) { + return new ActionsResponse(actions.stream() + .map(ActionResponse2::of) + .toList()); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/BillActionDetailResponse.java b/server/src/main/java/server/haengdong/presentation/response/BillActionDetailResponse.java new file mode 100644 index 000000000..10f71b82e --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/BillActionDetailResponse.java @@ -0,0 +1,18 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.BillActionDetailAppResponse; + +public record BillActionDetailResponse( + String name, + Long price, + boolean isFixed +) { + + public static BillActionDetailResponse of(BillActionDetailAppResponse billActionDetailAppResponse) { + return new BillActionDetailResponse( + billActionDetailAppResponse.name(), + billActionDetailAppResponse.price(), + billActionDetailAppResponse.isFixed() + ); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/BillActionDetailsResponse.java b/server/src/main/java/server/haengdong/presentation/response/BillActionDetailsResponse.java new file mode 100644 index 000000000..182e76db6 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/BillActionDetailsResponse.java @@ -0,0 +1,16 @@ +package server.haengdong.presentation.response; + +import java.util.List; +import java.util.stream.Collectors; +import server.haengdong.application.response.BillActionDetailsAppResponse; + +public record BillActionDetailsResponse( + List<BillActionDetailResponse> members +) { + + public static BillActionDetailsResponse of(BillActionDetailsAppResponse billActionDetailsAppResponse) { + return billActionDetailsAppResponse.billActionDetailAppResponses().stream() + .map(BillActionDetailResponse::of) + .collect(Collectors.collectingAndThen(Collectors.toList(), BillActionDetailsResponse::new)); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java b/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java new file mode 100644 index 000000000..289cca4fa --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java @@ -0,0 +1,15 @@ +package server.haengdong.presentation.response; + +import java.util.List; +import server.haengdong.application.response.CurrentMemberAppResponse; + +public record CurrentMembersResponse(List<String> memberNames) { + + public static CurrentMembersResponse of(List<CurrentMemberAppResponse> currentMembers) { + List<String> responses = currentMembers.stream() + .map(CurrentMemberAppResponse::name) + .toList(); + + return new CurrentMembersResponse(responses); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java b/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java new file mode 100644 index 000000000..c18694393 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.EventDetailAppResponse; + +public record EventDetailResponse(String eventName) { + + public static EventDetailResponse of(EventDetailAppResponse response) { + return new EventDetailResponse(response.eventName()); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/EventResponse.java b/server/src/main/java/server/haengdong/presentation/response/EventResponse.java new file mode 100644 index 000000000..506f5e814 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/EventResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.EventAppResponse; + +public record EventResponse(String eventId) { + + public static EventResponse of(EventAppResponse eventAppResponse) { + return new EventResponse(eventAppResponse.token()); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java new file mode 100644 index 000000000..0ea409202 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.MemberBillReportAppResponse; + +public record MemberBillReportResponse(String name, Long price) { + + public static MemberBillReportResponse of(MemberBillReportAppResponse memberBillReportAppResponse) { + return new MemberBillReportResponse(memberBillReportAppResponse.name(), memberBillReportAppResponse.price()); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java new file mode 100644 index 000000000..d350c4009 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java @@ -0,0 +1,15 @@ +package server.haengdong.presentation.response; + +import java.util.List; +import server.haengdong.application.response.MemberBillReportAppResponse; + +public record MemberBillReportsResponse(List<MemberBillReportResponse> reports) { + + public static MemberBillReportsResponse of(List<MemberBillReportAppResponse> memberBillReports) { + List<MemberBillReportResponse> reports = memberBillReports.stream() + .map(MemberBillReportResponse::of) + .toList(); + + return new MemberBillReportsResponse(reports); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/MembersResponse.java b/server/src/main/java/server/haengdong/presentation/response/MembersResponse.java new file mode 100644 index 000000000..0947d9e02 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/MembersResponse.java @@ -0,0 +1,13 @@ +package server.haengdong.presentation.response; + +import java.util.List; +import server.haengdong.application.response.MembersAppResponse; + +public record MembersResponse( + List<String> memberNames +) { + + public static MembersResponse of(MembersAppResponse response) { + return new MembersResponse(response.memberNames()); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/StepResponse.java b/server/src/main/java/server/haengdong/presentation/response/StepResponse.java new file mode 100644 index 000000000..55dd62c58 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/StepResponse.java @@ -0,0 +1,27 @@ +package server.haengdong.presentation.response; + +import java.util.ArrayList; +import java.util.List; +import server.haengdong.application.response.ActionAppResponse; + +public record StepResponse( + String stepName, + String type, + List<String> members, + List<ActionResponse> actions +) { + public static StepResponse of(String stepName, List<String> members, List<ActionAppResponse> actions) { + return new StepResponse( + stepName, + actions.get(0).actionTypeName(), + new ArrayList<>(members), + toActionsResponse(actions) + ); + } + + private static List<ActionResponse> toActionsResponse(List<ActionAppResponse> actions) { + return actions.stream() + .map(ActionResponse::of) + .toList(); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/StepsResponse.java b/server/src/main/java/server/haengdong/presentation/response/StepsResponse.java new file mode 100644 index 000000000..5f7573d67 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/StepsResponse.java @@ -0,0 +1,56 @@ +package server.haengdong.presentation.response; + +import java.util.ArrayList; +import java.util.List; +import server.haengdong.application.response.ActionAppResponse; +import server.haengdong.application.response.ActionAppResponse.ActionType; + +public record StepsResponse(List<StepResponse> steps) { + + public static StepsResponse of(List<ActionAppResponse> actions) { + List<StepResponse> steps = new ArrayList<>(); + List<String> currentMembers = new ArrayList<>(); + List<List<ActionAppResponse>> groups = createGroups(actions); + + int billStepCount = 0; + for (List<ActionAppResponse> group : groups) { + changeCurrentMembers(group, currentMembers); + if (group.get(0).actionType() == ActionType.BILL) { + billStepCount++; + } + StepResponse stepResponse = StepResponse.of(billStepCount + "์ฐจ", currentMembers, group); + steps.add(stepResponse); + } + return new StepsResponse(steps); + } + + private static List<List<ActionAppResponse>> createGroups(List<ActionAppResponse> actions) { + List<List<ActionAppResponse>> groups = new ArrayList<>(); + + for (ActionAppResponse action : actions) { + if (groups.isEmpty() || isActionTypeChange(action, groups)) { + groups.add(new ArrayList<>()); + } + groups.get(groups.size() - 1).add(action); + } + + return groups; + } + + private static boolean isActionTypeChange(ActionAppResponse action, List<List<ActionAppResponse>> groups) { + List<ActionAppResponse> currentGroup = groups.get(groups.size() - 1); + return currentGroup.get(0).actionType() != action.actionType(); + } + + private static void changeCurrentMembers(List<ActionAppResponse> group, List<String> currentMembers) { + for (ActionAppResponse action : group) { + if (action.actionType() == ActionType.IN) { + currentMembers.add(action.name()); + continue; + } + if (action.actionType() == ActionType.OUT) { + currentMembers.remove(action.name()); + } + } + } +} diff --git a/server/src/main/resources/application.yml b/server/src/main/resources/application.yml new file mode 100644 index 000000000..2ae503547 --- /dev/null +++ b/server/src/main/resources/application.yml @@ -0,0 +1,66 @@ +spring: + datasource: + driver-class-name: org.h2.Driver + url: jdbc:h2:mem:database + username: sa + password: + + h2: + console: + enabled: true + path: /h2-console + + jpa: + hibernate: + ddl-auto: create + properties: + hibernate: + format_sql: true + jdbc.time_zone: Asia/Seoul + show-sql: true + +cors: + max-age: 3600 + allowed-origins: http://localhost:3000, https://haengdong.pro, https://dev.haengdong.pro, https://app.haengdong.pro + +security: + jwt: + token: + secret-key: skdmeejEKJdkDjklDlkj123DKLJ3kDkeDkDKQMEOD1D90D8dE + expire-length: 604800000 # 1์ฃผ์ผ + +cookie: + http-only: false + secure: false + path: / + same-site: none + max-age: 7D + +management: + endpoints: + web: + exposure: + include: health, metrics, logfile + +server: + servlet: + encoding: + charset: UTF-8 + enabled: true + force: true + +--- + +spring: + config: + import: classpath:config/application-prod.yml + activate: + on-profile: prod + +--- + +spring: + config: + import: classpath:config/application-dev.yml + activate: + on-profile: dev diff --git a/server/src/main/resources/config b/server/src/main/resources/config new file mode 160000 index 000000000..fa4270674 --- /dev/null +++ b/server/src/main/resources/config @@ -0,0 +1 @@ +Subproject commit fa42706743e6eb3f4fd8c34618614eff8ae94b3d diff --git a/server/src/main/resources/logback-spring.xml b/server/src/main/resources/logback-spring.xml new file mode 100644 index 000000000..283b966a3 --- /dev/null +++ b/server/src/main/resources/logback-spring.xml @@ -0,0 +1,97 @@ +<configuration> + <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <!-- ์ฝ˜์†”์— ๋กœ๊ทธ ์ถœ๋ ฅ ํ˜•์‹ --> + <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> + </encoder> + </appender> + + <appender name="ERROR-ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <filter class="ch.qos.logback.classic.filter.LevelFilter"> + <level>ERROR</level> + <onMatch>ACCEPT</onMatch> + <onMismatch>DENY</onMismatch> + </filter> + <file>logs/spring-boot-application-error.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>logs/spring-boot-application-error.%d{yyyy-MM-dd}.log</fileNamePattern> + <maxHistory>30</maxHistory> + </rollingPolicy> + <encoder> + <!-- ๋‚ ์งœ, ์‹œ๊ฐ„, ๋กœ๊ทธ ๋ ˆ๋ฒจ, ์Šค๋ ˆ๋“œ ์ด๋ฆ„, ๋กœ๊ฑฐ ์ด๋ฆ„, ๋ฉ”์‹œ์ง€ ํ˜•์‹ --> + <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> + </encoder> + </appender> + + <appender name="WARN-ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <filter class="ch.qos.logback.classic.filter.LevelFilter"> + <level>WARN</level> + <onMatch>ACCEPT</onMatch> + <onMismatch>DENY</onMismatch> + </filter> + <file>logs/spring-boot-application-warn.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>logs/spring-boot-application-warn.%d{yyyy-MM-dd}.log</fileNamePattern> + <maxHistory>30</maxHistory> + </rollingPolicy> + <encoder> + <!-- ๋‚ ์งœ, ์‹œ๊ฐ„, ๋กœ๊ทธ ๋ ˆ๋ฒจ, ์Šค๋ ˆ๋“œ ์ด๋ฆ„, ๋กœ๊ฑฐ ์ด๋ฆ„, ๋ฉ”์‹œ์ง€ ํ˜•์‹ --> + <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> + </encoder> + </appender> + + <appender name="INFO-ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <filter class="ch.qos.logback.classic.filter.LevelFilter"> + <level>INFO</level> + <onMatch>ACCEPT</onMatch> + <onMismatch>DENY</onMismatch> + </filter> + <file>logs/spring-boot-application-info.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>logs/spring-boot-application-info.%d{yyyy-MM-dd}.log</fileNamePattern> + <maxHistory>30</maxHistory> + </rollingPolicy> + <encoder> + <!-- ๋‚ ์งœ, ์‹œ๊ฐ„, ๋กœ๊ทธ ๋ ˆ๋ฒจ, ์Šค๋ ˆ๋“œ ์ด๋ฆ„, ๋กœ๊ฑฐ ์ด๋ฆ„, ๋ฉ”์‹œ์ง€ ํ˜•์‹ --> + <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> + </encoder> + </appender> + + <appender name="DEBUG-ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <filter class="ch.qos.logback.classic.filter.LevelFilter"> + <level>DEBUG</level> + <onMatch>ACCEPT</onMatch> + <onMismatch>DENY</onMismatch> + </filter> + <file>logs/spring-boot-application-debug.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>logs/spring-boot-application-debug.%d{yyyy-MM-dd}.log</fileNamePattern> + <maxHistory>30</maxHistory> + </rollingPolicy> + <encoder> + <!-- ๋‚ ์งœ, ์‹œ๊ฐ„, ๋กœ๊ทธ ๋ ˆ๋ฒจ, ์Šค๋ ˆ๋“œ ์ด๋ฆ„, ๋กœ๊ฑฐ ์ด๋ฆ„, ๋ฉ”์‹œ์ง€ ํ˜•์‹ --> + <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> + </encoder> + </appender> + + <springProfile name="default"> + <root level="INFO"> + <appender-ref ref="CONSOLE"/> + </root> + </springProfile> + + <springProfile name="dev"> + <root level="INFO"> + <appender-ref ref="ERROR-ROLLING"/> + <appender-ref ref="WARN-ROLLING"/> + <appender-ref ref="INFO-ROLLING"/> + <appender-ref ref="DEBUG-ROLLING"/> + </root> + </springProfile> + + <springProfile name="prod"> + <root level="ERROR"> + <appender-ref ref="ERROR-ROLLING"/> + </root> + </springProfile> +</configuration> diff --git a/server/src/test/java/server/haengdong/application/ActionServiceTest.java b/server/src/test/java/server/haengdong/application/ActionServiceTest.java new file mode 100644 index 000000000..ee979b278 --- /dev/null +++ b/server/src/test/java/server/haengdong/application/ActionServiceTest.java @@ -0,0 +1,91 @@ +package server.haengdong.application; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.tuple; +import static server.haengdong.domain.action.MemberActionStatus.IN; +import static server.haengdong.domain.action.MemberActionStatus.OUT; +import static server.haengdong.support.fixture.Fixture.BILL_ACTION; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import server.haengdong.application.response.MemberBillReportAppResponse; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionDetail; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; +import server.haengdong.support.fixture.Fixture; + +class ActionServiceTest extends ServiceTestSupport { + + @Autowired + private ActionService actionService; + + @Autowired + private EventRepository eventRepository; + + @Autowired + private BillActionRepository billActionRepository; + + @Autowired + private MemberActionRepository memberActionRepository; + + @DisplayName("์ฐธ์—ฌ์ž๋ณ„ ์ •์‚ฐ ํ˜„ํ™ฉ์„ ์กฐํšŒํ•œ๋‹ค.") + @Test + void getMemberBillReports() { + Event event = Fixture.EVENT1; + Event savedEvent = eventRepository.save(event); + List<MemberAction> memberActions = List.of( + new MemberAction(new Action(savedEvent, 1L), "์†Œํ•˜", IN, 1L), + new MemberAction(new Action(savedEvent, 2L), "๊ฐ์ž", IN, 1L), + new MemberAction(new Action(savedEvent, 3L), "์ฟ ํ‚ค", IN, 1L), + new MemberAction(new Action(savedEvent, 5L), "๊ฐ์ž", OUT, 2L) + ); + List<BillAction> billActions = List.of( + new BillAction(new Action(savedEvent, 4L), "๋ฝ•์กฑ", 60_000L), + new BillAction(new Action(savedEvent, 7L), "์ธ์ƒ๋„ค์ปท", 20_000L) + ); + billActions.get(0).addDetails( + List.of( + new BillActionDetail(BILL_ACTION, "์†Œํ•˜", 10_000L, false), + new BillActionDetail(BILL_ACTION, "๊ฐ์ž", 40_000L, true), + new BillActionDetail(BILL_ACTION, "์ฟ ํ‚ค", 10_000L, false) + ) + ); + billActions.get(1).addDetails( + List.of( + new BillActionDetail(BILL_ACTION, "์†Œํ•˜", 5_000L, true), + new BillActionDetail(BILL_ACTION, "์ฟ ํ‚ค", 15_000L, true) + ) + ); + memberActionRepository.saveAll(memberActions); + billActionRepository.saveAll(billActions); + + List<MemberBillReportAppResponse> responses = actionService.getMemberBillReports(event.getToken()); + + assertThat(responses) + .hasSize(3) + .extracting(MemberBillReportAppResponse::name, MemberBillReportAppResponse::price) + .containsExactlyInAnyOrder( + tuple("๊ฐ์ž", 40_000L), + tuple("์ฟ ํ‚ค", 25_000L), + tuple("์†Œํ•˜", 15_000L) + ); + } + + @DisplayName("์กด์žฌํ•˜์ง€ ์•Š๋Š” ์ด๋ฒคํŠธ์˜ ์ฐธ์—ฌ์ž๋ณ„ ์ •์‚ฐ ํ˜„ํ™ฉ์„ ์กฐํšŒํ•˜๋Š” ๊ฒฝ์šฐ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @Test + void getMemberBillReports1() { + assertThatThrownBy(() -> actionService.getMemberBillReports("invalid token")) + .isInstanceOf(HaengdongException.class) + .hasMessage(HaengdongErrorCode.EVENT_NOT_FOUND.getMessage()); + } +} diff --git a/server/src/test/java/server/haengdong/application/BillActionDetailServiceTest.java b/server/src/test/java/server/haengdong/application/BillActionDetailServiceTest.java new file mode 100644 index 000000000..7074ce846 --- /dev/null +++ b/server/src/test/java/server/haengdong/application/BillActionDetailServiceTest.java @@ -0,0 +1,111 @@ +package server.haengdong.application; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.tuple; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import server.haengdong.application.request.BillActionDetailUpdateAppRequest; +import server.haengdong.application.request.BillActionDetailsUpdateAppRequest; +import server.haengdong.application.response.BillActionDetailAppResponse; +import server.haengdong.application.response.BillActionDetailsAppResponse; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionDetail; +import server.haengdong.domain.action.BillActionDetailRepository; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongException; +import server.haengdong.support.fixture.Fixture; + +class BillActionDetailServiceTest extends ServiceTestSupport { + + @Autowired + private BillActionDetailService billActionDetailService; + + @Autowired + private EventRepository eventRepository; + + @Autowired + private BillActionRepository billActionRepository; + + @Autowired + private BillActionDetailRepository billActionDetailRepository; + + @DisplayName("์ฐธ์—ฌ์ž๋ณ„ ์ง€์ถœ ๊ธˆ์•ก์„ ์กฐํšŒํ•œ๋‹ค.") + @Test + void findBillActionDetailsTest() { + Event event1 = Fixture.EVENT1; + eventRepository.save(event1); + Action action = new Action(event1, 1L); + BillAction billAction = new BillAction(action, "๋ฝ•์กฑ", 10000L); + billActionRepository.save(billAction); + BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "ํ† ๋‹ค๋ฆฌ", 6000L, true); + BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "์ฟ ํ‚ค", 4000L, true); + billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2)); + + BillActionDetailsAppResponse response = billActionDetailService.findBillActionDetails( + event1.getToken(), action.getId()); + + assertThat(response.billActionDetailAppResponses()).hasSize(2) + .extracting(BillActionDetailAppResponse::name, BillActionDetailAppResponse::price) + .containsExactly( + tuple("ํ† ๋‹ค๋ฆฌ", 6000L), + tuple("์ฟ ํ‚ค", 4000L) + ); + } + + @DisplayName("์ง€์ถœ ๊ธˆ์•ก ์ˆ˜์ • ์š”์ฒญ์˜ ์ดํ•ฉ์ด ์ง€์ถœ ๊ธˆ์•ก๊ณผ ์ผ์น˜ํ•˜์ง€ ์•Š์œผ๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @Test + void updateBillActionDetailsTest1() { + Event event1 = Fixture.EVENT1; + eventRepository.save(event1); + Action action = new Action(event1, 1L); + BillAction billAction = new BillAction(action, "๋ฝ•์กฑ", 10000L); + billActionRepository.save(billAction); + BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "ํ† ๋‹ค๋ฆฌ", 5000L, false); + BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "์ฟ ํ‚ค", 5000L, false); + billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2)); + + BillActionDetailsUpdateAppRequest request = new BillActionDetailsUpdateAppRequest(List.of( + new BillActionDetailUpdateAppRequest("ํ† ๋‹ค๋ฆฌ", 3000L, true), + new BillActionDetailUpdateAppRequest("์ฟ ํ‚ค", 4000L, true) + )); + assertThatCode( + () -> billActionDetailService.updateBillActionDetails(event1.getToken(), action.getId(), request)) + .isInstanceOf(HaengdongException.class) + .hasMessage("์ง€์ถœ ์ด์•ก์ด ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."); + } + + @DisplayName("์ง€์ถœ ๊ณ ์ • ๊ธˆ์•ก์„ ์ˆ˜์ •ํ•œ๋‹ค.") + @Test + void updateBillActionDetailsTest2() { + Event event1 = Fixture.EVENT1; + eventRepository.save(event1); + Action action = new Action(event1, 1L); + BillAction billAction = new BillAction(action, "๋ฝ•์กฑ", 10000L); + billActionRepository.save(billAction); + BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "ํ† ๋‹ค๋ฆฌ", 5000L, false); + BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "์ฟ ํ‚ค", 5000L, false); + billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2)); + + BillActionDetailsUpdateAppRequest request = new BillActionDetailsUpdateAppRequest(List.of( + new BillActionDetailUpdateAppRequest("ํ† ๋‹ค๋ฆฌ", 3000L, true), + new BillActionDetailUpdateAppRequest("์ฟ ํ‚ค", 7000L, true) + )); + billActionDetailService.updateBillActionDetails(event1.getToken(), action.getId(), request); + + List<BillActionDetail> results = billActionDetailRepository.findAll(); + + assertThat(results).hasSize(2) + .extracting(BillActionDetail::getMemberName, BillActionDetail::getPrice) + .containsExactly( + tuple("ํ† ๋‹ค๋ฆฌ", 3000L), + tuple("์ฟ ํ‚ค", 7000L) + ); + } +} diff --git a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java new file mode 100644 index 000000000..39e52f80c --- /dev/null +++ b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java @@ -0,0 +1,229 @@ +package server.haengdong.application; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.tuple; +import static org.junit.jupiter.api.Assertions.assertAll; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import server.haengdong.application.request.BillActionAppRequest; +import server.haengdong.application.request.BillActionUpdateAppRequest; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionDetail; +import server.haengdong.domain.action.BillActionDetailRepository; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.action.MemberActionStatus; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongException; +import server.haengdong.support.fixture.Fixture; + +class BillActionServiceTest extends ServiceTestSupport { + + @Autowired + private BillActionService billActionService; + + @Autowired + private EventRepository eventRepository; + + @Autowired + private BillActionRepository billActionRepository; + + @Autowired + private BillActionDetailRepository billActionDetailRepository; + + @Autowired + private MemberActionRepository memberActionRepository; + + @DisplayName("์ง€์ถœ ๋‚ด์—ญ์„ ์ƒ์„ฑํ•œ๋‹ค.") + @Test + void saveAllBillAction() { + Event event = Fixture.EVENT1; + Event savedEvent = eventRepository.save(event); + Action action1 = new Action(event, 1L); + Action action2 = new Action(event, 2L); + MemberAction memberAction1 = new MemberAction(action1, "๋ฐฑํ˜ธ", MemberActionStatus.IN, 1L); + MemberAction memberAction2 = new MemberAction(action2, "๋ง์ตธ", MemberActionStatus.IN, 2L); + memberActionRepository.saveAll(List.of(memberAction1, memberAction2)); + + List<BillActionAppRequest> requests = List.of( + new BillActionAppRequest("๋ฝ•์กฑ", 10_000L), + new BillActionAppRequest("์ธ์ƒ๋งฅ์ฃผ", 15_000L) + ); + + billActionService.saveAllBillAction(event.getToken(), requests); + + List<BillAction> actions = billActionRepository.findByAction_Event(savedEvent); + + assertThat(actions).extracting(BillAction::getTitle, BillAction::getPrice, BillAction::getSequence) + .containsExactlyInAnyOrder( + tuple("๋ฝ•์กฑ", 10_000L, 3L), + tuple("์ธ์ƒ๋งฅ์ฃผ", 15_000L, 4L) + ); + } + + @DisplayName("์ง€์ถœ ๋‚ด์—ญ์„ ์ƒ์„ฑํ•˜๋ฉด ์ง€์ถœ ์ƒ์„ธ ๋‚ด์—ญ์ด ์ƒ์„ฑ๋œ๋‹ค.") + @Test + void saveAllBillActionTest1() { + Event event = Fixture.EVENT1; + Event savedEvent = eventRepository.save(event); + Action action1 = new Action(event, 1L); + Action action2 = new Action(event, 2L); + MemberAction memberAction1 = new MemberAction(action1, "๋ฐฑํ˜ธ", MemberActionStatus.IN, 1L); + MemberAction memberAction2 = new MemberAction(action2, "๋ง์ตธ", MemberActionStatus.IN, 2L); + memberActionRepository.saveAll(List.of(memberAction1, memberAction2)); + + List<BillActionAppRequest> request = List.of( + new BillActionAppRequest("๋ฝ•์กฑ", 10_000L), + new BillActionAppRequest("์ธ์ƒ๋งฅ์ฃผ", 15_000L) + ); + + billActionService.saveAllBillAction(event.getToken(), request); + + List<BillActionDetail> billActionDetails = billActionDetailRepository.findAll(); + + assertThat(billActionDetails) + .hasSize(4) + .extracting("memberName", "price") + .containsExactlyInAnyOrder( + tuple("๋ฐฑํ˜ธ", 5_000L), + tuple("๋ง์ตธ", 5_000L), + tuple("๋ฐฑํ˜ธ", 7_500L), + tuple("๋ง์ตธ", 7_500L) + ); + } + + @DisplayName("์ด๋ฒคํŠธ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ์ง€์ถœ ๋‚ด์—ญ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์—†๋‹ค.") + @Test + void saveAllBillAction1() { + List<BillActionAppRequest> requests = List.of( + new BillActionAppRequest("๋ฝ•์กฑ", 10_000L), + new BillActionAppRequest("์ธ์ƒ๋งฅ์ฃผ", 15_000L) + ); + + assertThatThrownBy(() -> billActionService.saveAllBillAction("token", requests)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("์ง€์ถœ ์•ก์…˜์„ ์ˆ˜์ •ํ•œ๋‹ค.") + @Test + void updateBillAction() { + Event event = Fixture.EVENT1; + Event savedEvent = eventRepository.save(event); + Action action = Action.createFirst(savedEvent); + BillAction billAction = new BillAction(action, "๋ฝ•์กฑ", 10_000L); + BillAction savedBillAction = billActionRepository.save(billAction); + + Long actionId = savedBillAction.getAction().getId(); + BillActionUpdateAppRequest request = new BillActionUpdateAppRequest("์ธ์ƒ๋งฅ์ฃผ", 20_000L); + + billActionService.updateBillAction(event.getToken(), actionId, request); + + BillAction updatedBillAction = billActionRepository.findById(savedBillAction.getId()).get(); + + assertAll( + () -> assertThat(updatedBillAction.getTitle()).isEqualTo("์ธ์ƒ๋งฅ์ฃผ"), + () -> assertThat(updatedBillAction.getPrice()).isEqualTo(20_000L) + ); + } + + @DisplayName("ํ–‰์‚ฌ์— ์†ํ•˜์ง€ ์•Š์€ ์ง€์ถœ ์•ก์…˜์€ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†๋‹ค.") + @Test + void updateBillAction1() { + Event event1 = Fixture.EVENT1; + Event event2 = Fixture.EVENT2; + Event savedEvent1 = eventRepository.save(event1); + Event savedEvent2 = eventRepository.save(event2); + Action action1 = Action.createFirst(savedEvent1); + Action action2 = Action.createFirst(savedEvent2); + BillAction billAction1 = new BillAction(action1, "๋ฝ•์กฑ", 10_000L); + BillAction billAction2 = new BillAction(action2, "๋ฝ•์กฑ", 10_000L); + BillAction savedBillAction1 = billActionRepository.save(billAction1); + billActionRepository.save(billAction2); + + Long actionId = savedBillAction1.getAction().getId(); + BillActionUpdateAppRequest request = new BillActionUpdateAppRequest("์ธ์ƒ๋งฅ์ฃผ", 20_000L); + + assertThatThrownBy(() -> billActionService.updateBillAction(event2.getToken(), actionId, request)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("์ง€์ถœ ๋‚ด์—ญ ๊ธˆ์•ก์„ ๋ณ€๊ฒฝํ•˜๋ฉด ์ง€์ถœ ๋””ํ…Œ์ผ์ด ์ดˆ๊ธฐํ™” ๋œ๋‹ค.") + @Test + void updateBillAction2() { + Event event = Fixture.EVENT1; + Event savedEvent = eventRepository.save(event); + Action action = Action.createFirst(savedEvent); + BillAction billAction = new BillAction(action, "๋ฝ•์กฑ", 10_000L); + BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "๊ฐ์ž", 3000L, true); + BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "๊ณ ๊ตฌ๋งˆ", 2000L, true); + BillActionDetail billActionDetail3 = new BillActionDetail(billAction, "๋‹น๊ทผ", 3000L, true); + BillActionDetail billActionDetail4 = new BillActionDetail(billAction, "์–‘ํŒŒ", 2000L, true); + billAction.addDetails(List.of(billActionDetail1, billActionDetail2, billActionDetail3, billActionDetail4)); + BillAction savedBillAction = billActionRepository.save(billAction); + + Long actionId = savedBillAction.getAction().getId(); + BillActionUpdateAppRequest request = new BillActionUpdateAppRequest("์ธ์ƒ๋งฅ์ฃผ", 20_000L); + + billActionService.updateBillAction(event.getToken(), actionId, request); + + BillAction updatedBillAction = billActionRepository.findById(savedBillAction.getId()).get(); + List<BillActionDetail> billActionDetails = billActionDetailRepository.findAllByBillAction(updatedBillAction); + + assertThat(billActionDetails).hasSize(4) + .extracting("memberName", "price") + .containsExactlyInAnyOrder( + tuple("๊ฐ์ž", 5000L), + tuple("๊ณ ๊ตฌ๋งˆ", 5000L), + tuple("๋‹น๊ทผ", 5000L), + tuple("์–‘ํŒŒ", 5000L) + ); + } + + @DisplayName("์ง€์ถœ ๋‚ด์—ญ์„ ์‚ญ์ œํ•œ๋‹ค.") + @Test + void deleteBillAction() { + Event event = Fixture.EVENT1; + eventRepository.save(event); + BillAction billAction = new BillAction(new Action(event, 1L), "์ปคํ”ผ", 50_900L); + billActionRepository.save(billAction); + Long actionId = billAction.getAction().getId(); + + billActionService.deleteBillAction(event.getToken(), actionId); + + assertThat(billActionRepository.findById(billAction.getId())).isEmpty(); + } + + @DisplayName("์ง€์ถœ ๋‚ด์—ญ์„ ์‚ญ์ œํ•˜๋ฉด ์ง€์ถœ ์ƒ์„ธ๋„ ์‚ญ์ œ๋œ๋‹ค.") + @Test + void deleteBillActionTest1() { + Event event = Fixture.EVENT1; + eventRepository.save(event); + MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "๋ฐฑํ˜ธ", MemberActionStatus.IN, 1L); + MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "๋ง์ตธ", MemberActionStatus.IN, 2L); + BillAction billAction = new BillAction(new Action(event, 3L), "์ปคํ”ผ", 50_900L); + BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "๋ฐฑํ˜ธ", 25_450L, false); + BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "๋ง์ตธ", 25_450L, false); + memberActionRepository.saveAll(List.of(memberAction1, memberAction2)); + billActionRepository.save(billAction); + billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2)); + Long actionId = billAction.getAction().getId(); + + billActionService.deleteBillAction(event.getToken(), actionId); + + assertThat(billActionDetailRepository.findAll()).isEmpty(); + } + + @DisplayName("์ง€์ถœ ๋‚ด์—ญ ์‚ญ์ œ ์‹œ ํ–‰์‚ฌ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @Test + void deleteBillAction1() { + assertThatThrownBy(() -> billActionService.deleteBillAction("์†Œํ•˜๋ง์ตธ", 1L)) + .isInstanceOf(HaengdongException.class); + } +} diff --git a/server/src/test/java/server/haengdong/application/EventServiceTest.java b/server/src/test/java/server/haengdong/application/EventServiceTest.java new file mode 100644 index 000000000..407fa1457 --- /dev/null +++ b/server/src/test/java/server/haengdong/application/EventServiceTest.java @@ -0,0 +1,231 @@ +package server.haengdong.application; + + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.tuple; +import static org.mockito.BDDMockito.given; +import static server.haengdong.domain.action.MemberActionStatus.IN; +import static server.haengdong.domain.action.MemberActionStatus.OUT; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import server.haengdong.application.request.EventAppRequest; +import server.haengdong.application.request.MemberNameUpdateAppRequest; +import server.haengdong.application.request.MemberNamesUpdateAppRequest; +import server.haengdong.application.response.ActionAppResponse; +import server.haengdong.application.response.EventAppResponse; +import server.haengdong.application.response.EventDetailAppResponse; +import server.haengdong.application.response.MembersAppResponse; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.domain.event.EventTokenProvider; +import server.haengdong.exception.HaengdongException; +import server.haengdong.support.fixture.Fixture; + +class EventServiceTest extends ServiceTestSupport { + + @Autowired + private EventService eventService; + + @Autowired + private EventRepository eventRepository; + + @Autowired + private BillActionRepository billActionRepository; + + @Autowired + private MemberActionRepository memberActionRepository; + + @MockBean + private EventTokenProvider eventTokenProvider; + + @DisplayName("ํ–‰์‚ฌ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค") + @Test + void saveEventTest() { + EventAppRequest request = new EventAppRequest("test", "1234"); + given(eventTokenProvider.createToken()).willReturn("TOKEN"); + + EventAppResponse response = eventService.saveEvent(request); + + assertThat(response.token()).isEqualTo("TOKEN"); + } + + @DisplayName("ํ† ํฐ์œผ๋กœ ํ–‰์‚ฌ๋ฅผ ์กฐํšŒํ•œ๋‹ค.") + @Test + void findEventTest() { + Event event = Fixture.EVENT1; + eventRepository.save(event); + + EventDetailAppResponse eventDetailAppResponse = eventService.findEvent(event.getToken()); + + assertThat(eventDetailAppResponse.eventName()).isEqualTo(event.getName()); + } + + @DisplayName("ํ–‰์‚ฌ์— ์†ํ•œ ๋ชจ๋“  ์•ก์…˜์„ ์กฐํšŒํ•œ๋‹ค.") + @Test + void findActionsTest() { + Event event = Fixture.EVENT1; + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "ํ† ๋‹ค๋ฆฌ", IN, 1L); + Action action1 = new Action(event, 2L); + MemberAction memberAction1 = new MemberAction(action1, "์ฟ ํ‚ค", IN, 1L); + Action action2 = new Action(event, 3L); + BillAction billAction = new BillAction(action2, "๋ฝ•๋‚˜๋ฌด์Ÿ์ด์กฑ๋ฐœ", 30000L); + eventRepository.save(event); + memberActionRepository.saveAll(List.of(memberAction, memberAction1)); + billActionRepository.save(billAction); + + List<ActionAppResponse> actionAppResponses = eventService.findActions(event.getToken()); + + assertThat(actionAppResponses).hasSize(3) + .extracting(ActionAppResponse::actionId, + ActionAppResponse::name, + ActionAppResponse::price, + ActionAppResponse::sequence, + ActionAppResponse::actionTypeName) + .containsExactly( + tuple(1L, "ํ† ๋‹ค๋ฆฌ", null, 1L, "IN"), + tuple(2L, "์ฟ ํ‚ค", null, 2L, "IN"), + tuple(3L, "๋ฝ•๋‚˜๋ฌด์Ÿ์ด์กฑ๋ฐœ", 30000L, 3L, "BILL") + ); + } + + @DisplayName("ํ–‰์‚ฌ์— ์ฐธ์—ฌํ•œ ์ „์ฒด ์ธ์›์„ ์ค‘๋ณต ์—†์ด ์กฐํšŒํ•œ๋‹ค.") + @Test + void findAllMembersTest() { + Event event = Fixture.EVENT1; + Action action1 = new Action(event, 1L); + Action action2 = new Action(event, 2L); + Action action3 = new Action(event, 3L); + Action action4 = new Action(event, 4L); + BillAction billAction = new BillAction(action3, "๋ฝ•๋‚˜๋ฌด์Ÿ์ด์กฑ๋ฐœ", 30000L); + MemberAction memberAction1 = new MemberAction(action1, "ํ† ๋‹ค๋ฆฌ", IN, 1L); + MemberAction memberAction2 = new MemberAction(action2, "์ฟ ํ‚ค", IN, 1L); + MemberAction memberAction3 = new MemberAction(action4, "์ฟ ํ‚ค", OUT, 1L); + eventRepository.save(event); + billActionRepository.save(billAction); + memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3)); + + MembersAppResponse membersAppResponse = eventService.findAllMembers(event.getToken()); + + assertThat(membersAppResponse.memberNames()).containsExactlyInAnyOrder("ํ† ๋‹ค๋ฆฌ", "์ฟ ํ‚ค"); + } + + @DisplayName("ํ–‰์‚ฌ ์ฐธ์—ฌ ์ธ์›๋“ค์˜ ์ด๋ฆ„์„ ๋ณ€๊ฒฝํ•œ๋‹ค.") + @Test + void updateMember() { + Event event = Fixture.EVENT1; + MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "ํ† ๋‹ค๋ฆฌ", IN, 1L); + MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "์ฟ ํ‚ค", IN, 1L); + MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "์›จ๋””", IN, 2L); + MemberAction memberAction4 = new MemberAction(new Action(event, 4L), "์ฟ ํ‚ค", OUT, 3L); + MemberAction memberAction5 = new MemberAction(new Action(event, 5L), "์ฟ ํ‚ค", IN, 4L); + MemberAction memberAction6 = new MemberAction(new Action(event, 6L), "์ฟ ํ‚ค", OUT, 5L); + eventRepository.save(event); + memberActionRepository.saveAll(List.of( + memberAction1, memberAction2, memberAction3, memberAction4, memberAction5, memberAction6 + )); + + eventService.updateMember(event.getToken(), new MemberNamesUpdateAppRequest(List.of( + new MemberNameUpdateAppRequest("์ฟ ํ‚ค", "์ฟก์ฟก"), + new MemberNameUpdateAppRequest("ํ† ๋‹ค๋ฆฌ", "ํ† ์Ÿ์ด") + ))); + + List<MemberAction> foundMemberActions = memberActionRepository.findAllByEvent(event); + assertThat(foundMemberActions) + .extracting(MemberAction::getId, MemberAction::getMemberName) + .contains( + tuple(memberAction1.getId(), "ํ† ์Ÿ์ด"), + tuple(memberAction2.getId(), "์ฟก์ฟก"), + tuple(memberAction3.getId(), "์›จ๋””"), + tuple(memberAction4.getId(), "์ฟก์ฟก"), + tuple(memberAction5.getId(), "์ฟก์ฟก"), + tuple(memberAction6.getId(), "์ฟก์ฟก") + ); + } + + @DisplayName("์ด๋ฏธ ์กด์žฌํ•˜๋Š” ์ธ์›์˜ ์ด๋ฆ„์œผ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋‹ค.") + @Test + void updateMember1() { + Event event = Fixture.EVENT1; + MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "ํ† ๋‹ค๋ฆฌ", IN, 1L); + MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "์ฟ ํ‚ค", IN, 1L); + MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "์›จ๋””", IN, 2L); + eventRepository.save(event); + memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3)); + + MemberNamesUpdateAppRequest appRequest = new MemberNamesUpdateAppRequest(List.of( + new MemberNameUpdateAppRequest("์ฟ ํ‚ค", "์ฟก์ฟก"), + new MemberNameUpdateAppRequest("์›จ๋””", "ํ† ๋‹ค๋ฆฌ") + )); + + assertThatThrownBy(() -> eventService.updateMember(event.getToken(), appRequest)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("์กด์žฌํ•˜์ง€ ์•Š๋Š” ์ธ์›์€ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋‹ค.") + @Test + void updateMember2() { + Event event = Fixture.EVENT1; + MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "ํ† ๋‹ค๋ฆฌ", IN, 1L); + MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "์ฟ ํ‚ค", IN, 1L); + MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "์›จ๋””", IN, 2L); + eventRepository.save(event); + memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3)); + + MemberNamesUpdateAppRequest appRequest = new MemberNamesUpdateAppRequest(List.of( + new MemberNameUpdateAppRequest("์ฟก์ฟก", "ํ† ์Ÿ์ด"), + new MemberNameUpdateAppRequest("์›จ๋””", "๋ง๋ณต") + )); + + assertThatThrownBy(() -> eventService.updateMember(event.getToken(), appRequest)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("๋ณ€๊ฒฝ ์ „ ์ฐธ์—ฌ ์ธ์› ์ด๋ฆ„์ด ์ค‘๋ณต๋  ์ˆ˜ ์—†๋‹ค.") + @Test + void updateMember3() { + Event event = Fixture.EVENT1; + MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "ํ† ๋‹ค๋ฆฌ", IN, 1L); + MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "์ฟ ํ‚ค", IN, 1L); + MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "์›จ๋””", IN, 2L); + eventRepository.save(event); + memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3)); + + MemberNamesUpdateAppRequest appRequest = new MemberNamesUpdateAppRequest(List.of( + new MemberNameUpdateAppRequest("์ฟ ํ‚ค", "์ฟก์ฟก"), + new MemberNameUpdateAppRequest("์ฟ ํ‚ค", "ํ† ์Ÿ์ด") + )); + + assertThatThrownBy(() -> eventService.updateMember(event.getToken(), appRequest)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("๋ณ€๊ฒฝ ํ›„ ์ฐธ์—ฌ ์ธ์› ์ด๋ฆ„์ด ์ค‘๋ณต๋  ์ˆ˜ ์—†๋‹ค.") + @Test + void updateMember4() { + Event event = Fixture.EVENT1; + MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "ํ† ๋‹ค๋ฆฌ", IN, 1L); + MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "์ฟ ํ‚ค", IN, 1L); + MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "์›จ๋””", IN, 2L); + eventRepository.save(event); + memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3)); + + MemberNamesUpdateAppRequest appRequest = new MemberNamesUpdateAppRequest(List.of( + new MemberNameUpdateAppRequest("์ฟ ํ‚ค", "์ฟก์ฟก"), + new MemberNameUpdateAppRequest("ํ† ๋‹ค๋ฆฌ", "์ฟก์ฟก") + )); + + assertThatThrownBy(() -> eventService.updateMember(event.getToken(), appRequest)) + .isInstanceOf(HaengdongException.class); + } +} diff --git a/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java b/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java new file mode 100644 index 000000000..c04f06026 --- /dev/null +++ b/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java @@ -0,0 +1,223 @@ +package server.haengdong.application; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.tuple; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import server.haengdong.application.request.MemberActionSaveAppRequest; +import server.haengdong.application.request.MemberActionsSaveAppRequest; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.CurrentMembers; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.action.MemberActionStatus; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongException; +import server.haengdong.support.fixture.Fixture; + +class MemberActionFactoryTest extends ServiceTestSupport { + + @Autowired + private MemberActionFactory memberActionFactory; + + @Autowired + private MemberActionRepository memberActionRepository; + + @Autowired + private EventRepository eventRepository; + + @DisplayName("์ด์ „ ๋ฉค๋ฒ„ ์•ก์…˜์ด ์‹œํ€€์Šค ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌ๋˜์ง€ ์•Š์€ ์ƒํƒœ์—์„œ ์ƒˆ๋กœ์šด ๋ฉค๋ฒ„ ์•ก์…˜ ์š”์ฒญ์„ ๊ฒ€์ฆํ•œ๋‹ค.") + @Test + void createMemberActionsTest() { + Event event = eventRepository.save(Fixture.EVENT1); + Action action1 = new Action(event, 1L); + Action action2 = new Action(event, 2L); + MemberAction memberAction1 = new MemberAction(action1, "ํ† ๋‹ค๋ฆฌ", MemberActionStatus.IN, 1L); + MemberAction memberAction2 = new MemberAction(action2, "ํ† ๋‹ค๋ฆฌ", MemberActionStatus.OUT, 2L); + memberActionRepository.saveAll(List.of(memberAction1, memberAction2)); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("ํ† ๋‹ค๋ฆฌ", "OUT"))); + + List<MemberAction> unorderedMemberActions = List.of(memberAction2, memberAction1); + CurrentMembers currentMembers = CurrentMembers.of(unorderedMemberActions); + Action startAction = new Action(event, 3L); + + assertThatThrownBy(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("์ธ์› ๋ณ€๋™ ์•ก์…˜์„ ์ƒ์„ฑํ•œ๋‹ค.") + @Test + void createMemberActionsTest1() { + Event event = eventRepository.save(Fixture.EVENT1); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "ํ† ๋‹ค๋ฆฌ", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest memberActionsSaveAppRequest = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("ํ† ๋‹ค๋ฆฌ", "OUT"))); + Action startAction = new Action(event, 2L); + + CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); + List<MemberAction> memberActions = memberActionFactory.createMemberActions(memberActionsSaveAppRequest, + currentMembers, startAction + ); + + assertThat(memberActions).hasSize(1) + .extracting(MemberAction::getAction, MemberAction::getMemberName, MemberAction::getStatus) + .containsExactly( + tuple(startAction, "ํ† ๋‹ค๋ฆฌ", MemberActionStatus.OUT) + ); + } + + @DisplayName("ํ˜„์žฌ ํ–‰์‚ฌ์— ์ฐธ์—ฌ ์ค‘์ธ ๊ฒฝ์šฐ์— ํ‡ด์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.") + @Test + void createMemberActionsTest2() { + Event event = eventRepository.save(Fixture.EVENT1); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "ํ† ๋‹ค๋ฆฌ", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("ํ† ๋‹ค๋ฆฌ", "OUT"))); + Action startAction = new Action(event, 2L); + CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) + .doesNotThrowAnyException(); + } + + @DisplayName("ํ–‰์‚ฌ์—์„œ ํ‡ด์žฅํ•œ ๊ฒฝ์šฐ์— ์ž…์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.") + @Test + void createMemberActionsTest3() { + Event event = eventRepository.save(Fixture.EVENT1); + Action action1 = new Action(event, 1L); + MemberAction memberAction1 = new MemberAction(action1, "ํ† ๋‹ค๋ฆฌ", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction1); + Action action2 = new Action(event, 2L); + MemberAction memberAction2 = new MemberAction(action2, "ํ† ๋‹ค๋ฆฌ", MemberActionStatus.OUT, 2L); + memberActionRepository.save(memberAction2); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("ํ† ๋‹ค๋ฆฌ", "IN"))); + Action startAction = new Action(event, 3L); + CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction1, memberAction2)); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) + .doesNotThrowAnyException(); + } + + @DisplayName("ํ–‰์‚ฌ์— ์ž…์žฅํ•œ ์  ์—†๋Š” ๊ฒฝ์šฐ์— ์ž…์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.") + @Test + void createMemberActionsTest4() { + Event event = eventRepository.save(Fixture.EVENT1); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "ํ† ๋‹ค๋ฆฌ", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("์ฟ ํ‚ค", "IN"))); + Action startAction = new Action(event, 2L); + CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) + .doesNotThrowAnyException(); + } + + @DisplayName("ํ–‰์‚ฌ์— ์ž…์žฅํ•˜์ง€ ์•Š์•˜์„ ๊ฒฝ์šฐ ํ‡ด์žฅํ•  ์ˆ˜ ์—†๋‹ค.") + @Test + void createMemberActionTest5() { + Event event = eventRepository.save(Fixture.EVENT1); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("์ฟ ํ‚ค", "OUT"))); + Action startAction = new Action(event, 2L); + CurrentMembers currentMembers = CurrentMembers.of(List.of()); + + assertThatCode( + () -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("ํ–‰์‚ฌ์— ์ด๋ฏธ ์ฐธ์—ฌ ์ค‘์ธ ๊ฒฝ์šฐ ๋‹ค์‹œ ์ž…์žฅํ•  ์ˆ˜ ์—†๋‹ค.") + @Test + void createMemberActionTest6() { + Event event = eventRepository.save(Fixture.EVENT1); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "์ฟ ํ‚ค", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("์ฟ ํ‚ค", "IN"))); + Action startAction = new Action(event, 2L); + CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("ํ•œ ๋ช…์˜ ์‚ฌ์šฉ์ž๋Š” ๋™์‹œ์— ์—ฌ๋Ÿฌ ๋ฒˆ ์ž…์žฅํ•  ์ˆ˜ ์—†๋‹ค.") + @Test + void createMemberActionTest7() { + Event event = eventRepository.save(Fixture.EVENT1); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of( + new MemberActionSaveAppRequest("์ฟ ํ‚ค", "IN"), + new MemberActionSaveAppRequest("์ฟ ํ‚ค", "IN") + )); + Action startAction = new Action(event, 1L); + CurrentMembers currentMembers = CurrentMembers.of(List.of()); + + assertThatCode( + () -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("ํ•œ ๋ช…์˜ ์‚ฌ์šฉ์ž๋Š” ๋™์‹œ์— ์—ฌ๋Ÿฌ ๋ฒˆ ํ‡ด์žฅํ•  ์ˆ˜ ์—†๋‹ค.") + @Test + void createMemberActionTest8() { + Event event = eventRepository.save(Fixture.EVENT1); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "์ฟ ํ‚ค", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of( + new MemberActionSaveAppRequest("์ฟ ํ‚ค", "OUT"), + new MemberActionSaveAppRequest("์ฟ ํ‚ค", "OUT") + )); + Action startAction = new Action(event, 2L); + CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("ํ•œ ๋ช…์˜ ์‚ฌ์šฉ์ž๋Š” ์ž…์žฅ๊ณผ ํ‡ด์žฅ์„ ๋™์‹œ์— ํ•  ์ˆ˜ ์—†๋‹ค.") + @Test + void createMemberActionTest9() { + Event event = eventRepository.save(Fixture.EVENT1); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "์ฟ ํ‚ค", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of( + new MemberActionSaveAppRequest("์ฟ ํ‚ค", "IN"), + new MemberActionSaveAppRequest("์ฟ ํ‚ค", "OUT") + )); + Action startAction = new Action(event, 2L); + CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) + .isInstanceOf(HaengdongException.class); + } +} diff --git a/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java b/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java new file mode 100644 index 000000000..b6d29444c --- /dev/null +++ b/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java @@ -0,0 +1,251 @@ +package server.haengdong.application; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.groups.Tuple.tuple; +import static server.haengdong.domain.action.MemberActionStatus.IN; +import static server.haengdong.domain.action.MemberActionStatus.OUT; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import server.haengdong.application.request.MemberActionSaveAppRequest; +import server.haengdong.application.request.MemberActionsSaveAppRequest; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionDetail; +import server.haengdong.domain.action.BillActionDetailRepository; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.action.MemberActionStatus; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongException; +import server.haengdong.support.fixture.Fixture; + +class MemberActionServiceTest extends ServiceTestSupport { + + @Autowired + private MemberActionService memberActionService; + + @Autowired + private MemberActionRepository memberActionRepository; + + @Autowired + private EventRepository eventRepository; + + @Autowired + private BillActionRepository billActionRepository; + + @Autowired + private BillActionDetailRepository billActionDetailRepository; + + @DisplayName("ํ˜„์žฌ ํ–‰์‚ฌ์— ์ฐธ์—ฌํ•˜๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ์— ๋‚˜๊ฐˆ ์ˆ˜ ์žˆ๋‹ค.") + @Test + void saveMemberActionTest() { + Event event = eventRepository.save(Fixture.EVENT1); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "๋ง์ตธ", IN, 1L); + memberActionRepository.save(memberAction); + + assertThatCode(() -> memberActionService.saveMemberAction(event.getToken(), new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("๋ง์ตธ", "OUT"))))) + .doesNotThrowAnyException(); + } + + @DisplayName("ํ–‰์‚ฌ์—์„œ ํ‡ด์žฅํ•œ ๊ฒฝ์šฐ์— ์ž…์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.") + @Test + void saveMemberActionTest1() { + Event event = eventRepository.save(Fixture.EVENT1); + Action actionOne = new Action(event, 1L); + MemberAction memberActionOne = new MemberAction(actionOne, "๋ง์ตธ", IN, 1L); + memberActionRepository.save(memberActionOne); + + Action actionTwo = new Action(event, 2L); + MemberAction memberActionTwo = new MemberAction(actionTwo, "๋ง์ตธ", OUT, 1L); + memberActionRepository.save(memberActionTwo); + + assertThatCode(() -> memberActionService.saveMemberAction(event.getToken(), new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("๋ง์ตธ", "IN"))))) + .doesNotThrowAnyException(); + } + + @DisplayName("ํ–‰์‚ฌ์— ์ž…์žฅํ•˜์ง€ ์•Š์•˜์„ ๊ฒฝ์šฐ ํ‡ด์žฅํ•  ์ˆ˜ ์—†๋‹ค.") + @Test + void saveMemberActionTest2() { + MemberActionsSaveAppRequest appRequest = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("TOKEN", "OUT"))); + + assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", appRequest)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("์ด๋ฒคํŠธ๊ฐ€ ์—†์œผ๋ฉด ํ˜„์žฌ ์ฐธ์—ฌ ์ธ์›์„ ์กฐํšŒํ•  ์ˆ˜ ์—†๋‹ค.") + @Test + void getCurrentMembers() { + assertThatThrownBy(() -> memberActionService.getCurrentMembers("token")) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("ํ–‰์‚ฌ์˜ ์ „์ฒด ์ฐธ์—ฌ์ž ์ค‘์—์„œ ํŠน์ • ์ฐธ์—ฌ์ž์˜ ๋งด๋ฒ„ ์•ก์…˜์„ ์ „๋ถ€ ์‚ญ์ œํ•œ๋‹ค.") + @Test + void deleteMember() { + Event event = Fixture.EVENT1; + eventRepository.save(event); + MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "์ฐธ์—ฌ์ž", IN, 1L); + MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "ํ† ๋‹ค๋ฆฌ", IN, 1L); + MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "์ฟ ํ‚ค", IN, 1L); + MemberAction memberAction4 = new MemberAction(new Action(event, 4L), "์†Œํ•˜", IN, 1L); + MemberAction memberAction5 = new MemberAction(new Action(event, 5L), "์›จ๋””", IN, 1L); + MemberAction memberAction6 = new MemberAction(new Action(event, 6L), "์ฐธ์—ฌ์ž", OUT, 1L); + memberActionRepository.saveAll( + List.of(memberAction1, memberAction2, memberAction3, memberAction4, memberAction5, memberAction6)); + + Event event2 = Fixture.EVENT2; + eventRepository.save(event2); + Action action2 = Action.createFirst(event2); + MemberAction anotherMemberAction = new MemberAction(action2, "์ฐธ์—ฌ์ž", IN, 1L); + memberActionRepository.save(anotherMemberAction); + + memberActionService.deleteMember(event.getToken(), "์ฐธ์—ฌ์ž"); + + List<MemberAction> memberActions = memberActionRepository.findAll(); + + assertThat(memberActions).hasSize(5) + .extracting("memberName", "status") + .containsExactly( + tuple("ํ† ๋‹ค๋ฆฌ", IN), + tuple("์ฟ ํ‚ค", IN), + tuple("์†Œํ•˜", IN), + tuple("์›จ๋””", IN), + tuple("์ฐธ์—ฌ์ž", IN) + ); + } + + @DisplayName("์ด๋ฒคํŠธ์— ์†ํ•œ ๋ฉค๋ฒ„์„ ์‚ญ์ œํ•˜๋ฉด ์ „์ฒด ์ง€์ถœ ๋‚ด์—ญ ๋””ํ…Œ์ผ์ด ์ดˆ๊ธฐํ™”๋œ๋‹ค.") + @Test + void deleteMember1() { + Event event = Fixture.EVENT1; + eventRepository.save(event); + MemberAction memberAction1 = createMemberAction(new Action(event, 1L), "ํ† ๋‹ค๋ฆฌ", IN, 1L); + Action targetAction = new Action(event, 2L); + MemberAction memberAction2 = createMemberAction(targetAction, "ํ† ๋‹ค๋ฆฌ", OUT, 2L); + MemberAction memberAction3 = createMemberAction(new Action(event, 3L), "์ฟ ํ‚ค", IN, 3L); + MemberAction memberAction4 = createMemberAction(new Action(event, 4L), "์›จ๋””", IN, 4L); + MemberAction memberAction5 = createMemberAction(new Action(event, 5L), "๊ฐ์ž", IN, 5L); + memberActionRepository.saveAll( + List.of(memberAction1, + memberAction2, + memberAction3, + memberAction4, + memberAction5 + ) + ); + BillAction billAction = new BillAction(new Action(event, 6L), "๋ฝ•์กฑ", 100_000L); + billActionRepository.save(billAction); + BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "์ฟ ํ‚ค", 40_000L, true); + BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "์›จ๋””", 30_000L, false); + BillActionDetail billActionDetail3 = new BillActionDetail(billAction, "๊ฐ์ž", 30_000L, false); + billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2, billActionDetail3)); + List<BillActionDetail> allByBillAction = billActionDetailRepository.findAllByBillAction(billAction); + System.out.println("allByBillAction = " + allByBillAction.isEmpty()); + + memberActionService.deleteMember(event.getToken(), "์ฟ ํ‚ค"); + + List<BillActionDetail> billActionDetails = billActionDetailRepository.findAllByBillAction(billAction); + + assertThat(billActionDetails).hasSize(2) + .extracting("memberName", "price") + .containsExactlyInAnyOrder( + tuple("์›จ๋””", 50_000L), + tuple("๊ฐ์ž", 50_000L) + ); + } + + @DisplayName("์ด๋ฒคํŠธ์— ์†ํ•œ ๋ฉค๋ฒ„ ์•ก์…˜์„ ์‚ญ์ œํ•˜๋ฉด ์ดํ›„์— ๊ธฐ๋ก๋œ ํ•ด๋‹น ์ฐธ์—ฌ์ž์˜ ๋ชจ๋“  ๋ฉค๋ฒ„ ์•ก์…˜์„ ์‚ญ์ œํ•œ๋‹ค.") + @Test + void deleteMemberAction() { + Event event = Fixture.EVENT1; + eventRepository.save(event); + MemberAction memberAction1 = createMemberAction(new Action(event, 1L), "ํ† ๋‹ค๋ฆฌ", IN, 1L); + Action targetAction = new Action(event, 2L); + MemberAction memberAction2 = createMemberAction(targetAction, "ํ† ๋‹ค๋ฆฌ", OUT, 2L); + MemberAction memberAction3 = createMemberAction(new Action(event, 3L), "์ฟ ํ‚ค", IN, 3L); + MemberAction memberAction4 = createMemberAction(new Action(event, 4L), "์›จ๋””", IN, 4L); + MemberAction memberAction5 = createMemberAction(new Action(event, 5L), "ํ† ๋‹ค๋ฆฌ", IN, 5L); + MemberAction memberAction6 = createMemberAction(new Action(event, 6L), "ํ† ๋‹ค๋ฆฌ", OUT, 6L); + MemberAction memberAction7 = createMemberAction(new Action(event, 7L), "์ฟ ํ‚ค", OUT, 7L); + memberActionRepository.saveAll( + List.of(memberAction1, + memberAction2, + memberAction3, + memberAction4, + memberAction5, + memberAction6, + memberAction7) + ); + + memberActionService.deleteMemberAction(event.getToken(), targetAction.getId()); + List<MemberAction> memberActions = memberActionRepository.findAll(); + + assertThat(memberActions).hasSize(4) + .extracting("id", "memberName", "status") + .containsExactly( + tuple(memberAction1.getId(), "ํ† ๋‹ค๋ฆฌ", IN), + tuple(memberAction3.getId(), "์ฟ ํ‚ค", IN), + tuple(memberAction4.getId(), "์›จ๋””", IN), + tuple(memberAction7.getId(), "์ฟ ํ‚ค", OUT) + ); + } + + @DisplayName("์ด๋ฒคํŠธ์— ์†ํ•œ ๋ฉค๋ฒ„ ์•ก์…˜์„ ์‚ญ์ œํ•˜๋ฉด ์ดํ›„ ์ง€์ถœ ๋‚ด์—ญ ๋””ํ…Œ์ผ์ด ์ดˆ๊ธฐํ™”๋œ๋‹ค.") + @Test + void deleteMemberAction1() { + Event event = Fixture.EVENT1; + eventRepository.save(event); + MemberAction memberAction1 = createMemberAction(new Action(event, 1L), "ํ† ๋‹ค๋ฆฌ", IN, 1L); + Action targetAction = new Action(event, 2L); + MemberAction memberAction2 = createMemberAction(targetAction, "ํ† ๋‹ค๋ฆฌ", OUT, 2L); + MemberAction memberAction3 = createMemberAction(new Action(event, 3L), "์ฟ ํ‚ค", IN, 3L); + MemberAction memberAction4 = createMemberAction(new Action(event, 4L), "์›จ๋””", IN, 4L); + MemberAction memberAction5 = createMemberAction(new Action(event, 5L), "๊ฐ์ž", IN, 5L); + memberActionRepository.saveAll( + List.of(memberAction1, + memberAction2, + memberAction3, + memberAction4, + memberAction5 + ) + ); + BillAction billAction = new BillAction(new Action(event, 6L), "๋ฝ•์กฑ", 100_000L); + billActionRepository.save(billAction); + BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "์ฟ ํ‚ค", 40_000L, true); + BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "์›จ๋””", 30_000L, false); + BillActionDetail billActionDetail3 = new BillActionDetail(billAction, "๊ฐ์ž", 30_000L, false); + billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2, billActionDetail3)); + + memberActionService.deleteMemberAction(event.getToken(), targetAction.getId()); + List<BillActionDetail> billActionDetails = billActionDetailRepository.findAllByBillAction(billAction); + + assertThat(billActionDetails).hasSize(4) + .extracting("memberName", "price") + .containsExactlyInAnyOrder( + tuple("ํ† ๋‹ค๋ฆฌ", 25_000L), + tuple("์ฟ ํ‚ค", 25_000L), + tuple("์›จ๋””", 25_000L), + tuple("๊ฐ์ž", 25_000L) + ); + } + + private MemberAction createMemberAction( + Action action, + String memberName, + MemberActionStatus memberActionStatus, + long memberGroupId + ) { + return new MemberAction(action, memberName, memberActionStatus, memberGroupId); + } +} diff --git a/server/src/test/java/server/haengdong/application/ServiceTestSupport.java b/server/src/test/java/server/haengdong/application/ServiceTestSupport.java new file mode 100644 index 000000000..b0e2db0a6 --- /dev/null +++ b/server/src/test/java/server/haengdong/application/ServiceTestSupport.java @@ -0,0 +1,11 @@ +package server.haengdong.application; + +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import server.haengdong.support.extension.DatabaseCleanerExtension; + +@ExtendWith(DatabaseCleanerExtension.class) +@SpringBootTest(webEnvironment= WebEnvironment.NONE) +abstract class ServiceTestSupport { +} diff --git a/server/src/test/java/server/haengdong/docs/ActionControllerDocsTest.java b/server/src/test/java/server/haengdong/docs/ActionControllerDocsTest.java new file mode 100644 index 000000000..39c2d0bb8 --- /dev/null +++ b/server/src/test/java/server/haengdong/docs/ActionControllerDocsTest.java @@ -0,0 +1,70 @@ +package server.haengdong.docs; + +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import server.haengdong.application.ActionService; +import server.haengdong.application.response.MemberBillReportAppResponse; +import server.haengdong.presentation.ActionController; + +class ActionControllerDocsTest extends RestDocsSupport { + + private final ActionService actionService = mock(ActionService.class); + + @Override + protected Object initController() { + return new ActionController(actionService); + } + + @DisplayName("์ฐธ์—ฌ์ž๋ณ„ ์ •์‚ฐ ํ˜„ํ™ฉ์„ ์กฐํšŒํ•œ๋‹ค.") + @Test + void getMemberBillReports() throws Exception { + List<MemberBillReportAppResponse> memberBillReportAppResponses = List.of( + new MemberBillReportAppResponse("์†Œํ•˜", 20_000L), new MemberBillReportAppResponse("ํ† ๋‹ค๋ฆฌ", 200_000L)); + + given(actionService.getMemberBillReports(any())).willReturn(memberBillReportAppResponses); + + mockMvc.perform(get("/api/events/{eventId}/actions/reports", "๋ง์ตธํ† ํฐ") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].name").value(equalTo("์†Œํ•˜"))) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].price").value(equalTo(20_000))) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].name").value(equalTo("ํ† ๋‹ค๋ฆฌ"))) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].price").value(equalTo(200_000))) + .andDo( + document("getMemberBillReports", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("ํ–‰์‚ฌ ID") + ), + responseFields( + fieldWithPath("reports").type(JsonFieldType.ARRAY).description("์ „์ฒด ์ •์‚ฐ ํ˜„ํ™ฉ ๋ชฉ๋ก"), + fieldWithPath("reports[0].name").type(JsonFieldType.STRING) + .description("์ฐธ์—ฌ์ž ์ด๋ฆ„"), + fieldWithPath("reports[0].price").type(JsonFieldType.NUMBER) + .description("์ฐธ์—ฌ์ž ์ •์‚ฐ ๊ธˆ์•ก") + )) + ); + } +} diff --git a/server/src/test/java/server/haengdong/docs/BillActionControllerDocsTest.java b/server/src/test/java/server/haengdong/docs/BillActionControllerDocsTest.java new file mode 100644 index 000000000..7ed6fe6c4 --- /dev/null +++ b/server/src/test/java/server/haengdong/docs/BillActionControllerDocsTest.java @@ -0,0 +1,128 @@ +package server.haengdong.docs; + +import static org.mockito.Mockito.mock; +import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName; +import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static server.haengdong.support.fixture.Fixture.EVENT_COOKIE; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import server.haengdong.application.BillActionService; +import server.haengdong.presentation.BillActionController; +import server.haengdong.presentation.request.BillActionSaveRequest; +import server.haengdong.presentation.request.BillActionUpdateRequest; +import server.haengdong.presentation.request.BillActionsSaveRequest; + +class BillActionControllerDocsTest extends RestDocsSupport { + + private final BillActionService billActionService = mock(BillActionService.class); + + @Override + protected Object initController() { + return new BillActionController(billActionService); + } + + @DisplayName("์ง€์ถœ ๋‚ด์—ญ์„ ์ƒ์„ฑํ•œ๋‹ค.") + @Test + void saveAllBillAction() throws Exception { + BillActionsSaveRequest request = new BillActionsSaveRequest( + List.of( + new BillActionSaveRequest("๋ฝ•์กฑ", 10_000L), + new BillActionSaveRequest("์ธ์ƒ๋งฅ์ฃผ", 10_000L) + ) + ); + String requestBody = objectMapper.writeValueAsString(request); + String eventId = "์ฟ ํ‚คํ† ํฐ"; + + mockMvc.perform(post("/api/events/{eventId}/bill-actions", eventId) + .contentType(MediaType.APPLICATION_JSON) + .cookie(EVENT_COOKIE) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()) + .andDo(document("createBillActions", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("ํ–‰์‚ฌ ID") + ), + requestCookies( + cookieWithName("eventToken").description("ํ–‰์‚ฌ ๊ด€๋ฆฌ์ž ํ† ํฐ") + ), + requestFields( + fieldWithPath("actions").description("์ƒ์„ฑํ•  ์ง€์ถœ ์•ก์…˜ ๋ชฉ๋ก"), + fieldWithPath("actions[0].title").description("์ƒ์„ฑํ•  ์ง€์ถœ ์•ก์…˜์˜ ์ œ๋ชฉ"), + fieldWithPath("actions[0].price").description("์ƒ์„ฑํ•  ์ง€์ถœ ์•ก์…˜์˜ ๊ธˆ์•ก") + ) + )); + } + + @DisplayName("์ง€์ถœ ์•ก์…˜์„ ์ˆ˜์ •ํ•œ๋‹ค.") + @Test + void updateBillAction() throws Exception { + BillActionUpdateRequest request = new BillActionUpdateRequest("๋ฝ•์กฑ", 10_000L); + + String requestBody = objectMapper.writeValueAsString(request); + String eventId = "์›จ๋””ํ† ํฐ"; + + mockMvc.perform(put("/api/events/{eventId}/bill-actions/{actionId}", eventId, 1L) + .cookie(EVENT_COOKIE) + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()) + .andDo(document("updateBillAction", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("ํ–‰์‚ฌ ID"), + parameterWithName("actionId").description("์ง€์ถœ ์•ก์…˜ ID") + ), + requestCookies( + cookieWithName("eventToken").description("ํ–‰์‚ฌ ๊ด€๋ฆฌ์ž ํ† ํฐ") + ), + requestFields( + fieldWithPath("title").description("์ˆ˜์ •ํ•  ์ง€์ถœ ์•ก์…˜์˜ ์ œ๋ชฉ"), + fieldWithPath("price").description("์ˆ˜์ •ํ•  ์ง€์ถœ ์•ก์…˜์˜ ๊ธˆ์•ก") + ) + )); + } + + @DisplayName("์ง€์ถœ ๋‚ด์—ญ์„ ์‚ญ์ œํ•œ๋‹ค.") + @Test + void deleteBillAction() throws Exception { + String eventId = "ํ† ๋‹ค๋ฆฌํ† ํฐ"; + + mockMvc.perform(delete("/api/events/{eventId}/bill-actions/{actionId}", eventId, 1) + .cookie(EVENT_COOKIE) + ) + .andDo(print()) + .andExpect(status().isOk()) + .andDo(document("deleteBillAction", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("ํ–‰์‚ฌ ID"), + parameterWithName("actionId").description("์ง€์ถœ ์•ก์…˜ ID") + ), + requestCookies( + cookieWithName("eventToken").description("ํ–‰์‚ฌ ๊ด€๋ฆฌ์ž ํ† ํฐ") + ) + )); + } +} diff --git a/server/src/test/java/server/haengdong/docs/BillActionDetailControllerDocsTest.java b/server/src/test/java/server/haengdong/docs/BillActionDetailControllerDocsTest.java new file mode 100644 index 000000000..f492195f3 --- /dev/null +++ b/server/src/test/java/server/haengdong/docs/BillActionDetailControllerDocsTest.java @@ -0,0 +1,127 @@ +package server.haengdong.docs; + +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName; +import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static server.haengdong.support.fixture.Fixture.EVENT_COOKIE; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; +import server.haengdong.application.BillActionDetailService; +import server.haengdong.application.response.BillActionDetailAppResponse; +import server.haengdong.application.response.BillActionDetailsAppResponse; +import server.haengdong.presentation.BillActionDetailController; +import server.haengdong.presentation.request.BillActionDetailUpdateRequest; +import server.haengdong.presentation.request.BillActionDetailsUpdateRequest; + +public class BillActionDetailControllerDocsTest extends RestDocsSupport { + + private final BillActionDetailService billActionDetailService = mock(BillActionDetailService.class); + + @Override + protected Object initController() { + return new BillActionDetailController(billActionDetailService); + } + + @DisplayName("์ฐธ์—ฌ์ž๋ณ„ ์ง€์ถœ ๊ธˆ์•ก์„ ์กฐํšŒํ•œ๋‹ค.") + @Test + void findBillActionDetailsTest() throws Exception { + BillActionDetailsAppResponse appResponse = new BillActionDetailsAppResponse( + List.of(new BillActionDetailAppResponse("ํ† ๋‹ค๋ฆฌ", 1000L, false))); + given(billActionDetailService.findBillActionDetails(anyString(), anyLong())) + .willReturn(appResponse); + + mockMvc.perform(get("/api/events/{eventId}/bill-actions/{actionId}/fixed", "TOKEN", 1L) + .cookie(EVENT_COOKIE)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.members").isArray()) + .andExpect(jsonPath("$.members[0].name").value("ํ† ๋‹ค๋ฆฌ")) + .andExpect(jsonPath("$.members[0].price").value(1000L)) + .andExpect(jsonPath("$.members[0].isFixed").value(false)) + .andDo( + document("findBillActionDetailsTest", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("ํ–‰์‚ฌ ID"), + parameterWithName("actionId").description("์•ก์…˜ ID") + ), requestCookies( + cookieWithName("eventToken").description("ํ–‰์‚ฌ ๊ด€๋ฆฌ์ž ํ† ํฐ") + ), responseFields( + fieldWithPath("members").type(JsonFieldType.ARRAY) + .description("์ „์ฒด ์ •์‚ฐ ์ˆ˜์ • ์š”์ฒญ ๋ชฉ๋ก"), + fieldWithPath("members[0].name").type(JsonFieldType.STRING) + .description("์ฐธ์—ฌ์ž ์ด๋ฆ„"), + fieldWithPath("members[0].price").type(JsonFieldType.NUMBER) + .description("์ฐธ์—ฌ์ž ์ •์‚ฐ ๊ธˆ์•ก"), + fieldWithPath("members[0].isFixed").type(JsonFieldType.BOOLEAN) + .description("์ฐธ์—ฌ์ž ์ •์‚ฐ ๊ธˆ์•ก ์ˆ˜์ • ์—ฌ๋ถ€") + ) + ) + ); + } + + @DisplayName("์ฐธ์—ฌ์ž๋ณ„ ์ง€์ถœ ๊ธˆ์•ก์„ ์ˆ˜์ •ํ•œ๋‹ค.") + @Test + void updateBillActionDetailsTest() throws Exception { + List<BillActionDetailUpdateRequest> billActionDetailUpdateRequests = List.of( + new BillActionDetailUpdateRequest("์†Œํ•˜", 10000L, true), + new BillActionDetailUpdateRequest("์›จ๋””", 20000L, true) + ); + BillActionDetailsUpdateRequest request = new BillActionDetailsUpdateRequest( + billActionDetailUpdateRequests); + + String json = objectMapper.writeValueAsString(request); + + mockMvc.perform(put("/api/events/{eventId}/bill-actions/{actionId}/fixed", "TOKEN", 1L) + .cookie(EVENT_COOKIE) + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andDo(print()) + .andExpect(status().isOk()) + .andDo( + document("updateBillActionDetailsTest", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("ํ–‰์‚ฌ ID"), + parameterWithName("actionId").description("์•ก์…˜ ID") + ), + requestCookies( + cookieWithName("eventToken").description("ํ–‰์‚ฌ ๊ด€๋ฆฌ์ž ํ† ํฐ") + ), + requestFields( + fieldWithPath("members").type(JsonFieldType.ARRAY) + .description("์ „์ฒด ์ •์‚ฐ ์ˆ˜์ • ์š”์ฒญ ๋ชฉ๋ก"), + fieldWithPath("members[0].name").type(JsonFieldType.STRING) + .description("์ฐธ์—ฌ์ž ์ด๋ฆ„"), + fieldWithPath("members[0].price").type(JsonFieldType.NUMBER) + .description("์ฐธ์—ฌ์ž ์ •์‚ฐ ๊ธˆ์•ก"), + fieldWithPath("members[0].isFixed").type(JsonFieldType.BOOLEAN) + .description("์ฐธ์—ฌ์ž ์ •์‚ฐ ๊ธˆ์•ก ์ˆ˜์ • ์—ฌ๋ถ€") + ) + ) + ); + } +} diff --git a/server/src/test/java/server/haengdong/docs/EventControllerDocsTest.java b/server/src/test/java/server/haengdong/docs/EventControllerDocsTest.java new file mode 100644 index 000000000..88de2a3a6 --- /dev/null +++ b/server/src/test/java/server/haengdong/docs/EventControllerDocsTest.java @@ -0,0 +1,381 @@ +package server.haengdong.docs; + +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName; +import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies; +import static org.springframework.restdocs.cookies.CookieDocumentation.responseCookies; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.cookie; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static server.haengdong.support.fixture.Fixture.EVENT_COOKIE; + +import java.time.Duration; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; +import server.haengdong.application.AuthService; +import server.haengdong.application.EventService; +import server.haengdong.application.request.EventAppRequest; +import server.haengdong.application.response.ActionAppResponse; +import server.haengdong.application.response.ActionAppResponse.ActionType; +import server.haengdong.application.response.EventAppResponse; +import server.haengdong.application.response.EventDetailAppResponse; +import server.haengdong.application.response.MembersAppResponse; +import server.haengdong.infrastructure.auth.CookieProperties; +import server.haengdong.presentation.EventController; +import server.haengdong.presentation.request.EventLoginRequest; +import server.haengdong.presentation.request.EventSaveRequest; +import server.haengdong.presentation.request.MemberNameUpdateRequest; +import server.haengdong.presentation.request.MemberNamesUpdateRequest; + +public class EventControllerDocsTest extends RestDocsSupport { + + private final EventService eventService = mock(EventService.class); + private final AuthService authService = mock(AuthService.class); + private final CookieProperties cookieProperties = new CookieProperties( + true, true, "domain", "path", "none", Duration.ofDays(7) + ); + + @Override + protected Object initController() { + return new EventController(eventService, authService, cookieProperties); + } + + @DisplayName("์ด๋ฒคํŠธ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.") + @Test + void saveEvent() throws Exception { + EventSaveRequest eventSaveRequest = new EventSaveRequest("ํ† ๋‹ค๋ฆฌ", "0987"); + String requestBody = objectMapper.writeValueAsString(eventSaveRequest); + String eventId = "์ฟ ํ‚ค ํ† ํฐ"; + EventAppResponse eventAppResponse = new EventAppResponse(eventId); + given(eventService.saveEvent(any(EventAppRequest.class))).willReturn(eventAppResponse); + given(authService.createToken(eventId)).willReturn("jwtToken"); + given(authService.getTokenName()).willReturn("eventToken"); + + mockMvc.perform(post("/api/events") + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(cookie().value("eventToken", "jwtToken")) + .andExpect(jsonPath("$.eventId").value("์ฟ ํ‚ค ํ† ํฐ")) + .andDo( + document("createEvent", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + requestFields( + fieldWithPath("eventName").type(JsonFieldType.STRING).description("ํ–‰์‚ฌ ์ด๋ฆ„"), + fieldWithPath("password").type(JsonFieldType.STRING).description("ํ–‰์‚ฌ ๋น„๋ฐ€ ๋ฒˆํ˜ธ") + ), + responseFields( + fieldWithPath("eventId").type(JsonFieldType.STRING) + .description("ํ–‰์‚ฌ ID") + ), + responseCookies( + cookieWithName("eventToken").description("ํ–‰์‚ฌ ๊ด€๋ฆฌ์ž์šฉ ํ† ํฐ") + ) + ) + ); + } + + @DisplayName("ํ† ํฐ์œผ๋กœ ํ–‰์‚ฌ๋ฅผ ์กฐํšŒํ•œ๋‹ค.") + @Test + void findEventTest() throws Exception { + String eventId = "๋ง์ตธํ† ํฐ"; + EventDetailAppResponse eventDetailAppResponse = new EventDetailAppResponse("ํ–‰๋™๋Œ€์žฅ ํšŒ์‹"); + given(eventService.findEvent(eventId)).willReturn(eventDetailAppResponse); + + mockMvc.perform(get("/api/events/{eventId}", eventId)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.eventName").value("ํ–‰๋™๋Œ€์žฅ ํšŒ์‹")) + .andDo( + document("getEvent", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("ํ–‰์‚ฌ ID") + ), + responseFields( + fieldWithPath("eventName").type(JsonFieldType.STRING).description("ํ–‰์‚ฌ ์ด๋ฆ„") + ) + ) + ); + } + + @DisplayName("ํ–‰์‚ฌ์— ์ฐธ์—ฌํ•œ ์ „์ฒด ์ธ์›์„ ์ค‘๋ณต ์—†์ด ์กฐํšŒํ•œ๋‹ค.") + @Test + void findAllMembersTest() throws Exception { + MembersAppResponse memberAppResponse = new MembersAppResponse(List.of("ํ† ๋‹ค๋ฆฌ", "์ฟ ํ‚ค")); + given(eventService.findAllMembers(anyString())).willReturn(memberAppResponse); + + mockMvc.perform(get("/api/events/{eventId}/members", "TOKEN")) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.memberNames").isArray()) + .andExpect(jsonPath("$.memberNames[0]").value("ํ† ๋‹ค๋ฆฌ")) + .andExpect(jsonPath("$.memberNames[1]").value("์ฟ ํ‚ค")) + .andDo( + document("findAllEventMember", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("ํ–‰์‚ฌ ID") + ), + responseFields( + fieldWithPath("memberNames").type(JsonFieldType.ARRAY) + .description("ํ–‰์‚ฌ ์ฐธ์—ฌ์ž ๋ชฉ๋ก") + ) + ) + ); + } + + @DisplayName("ํ–‰์‚ฌ ์ฐธ์—ฌ ์ธ์›์˜ ์ด๋ฆ„์„ ์ˆ˜์ •ํ•œ๋‹ค.") + @Test + void updateMember() throws Exception { + String token = "TOKEN"; + MemberNamesUpdateRequest memberNameUpdateRequest = new MemberNamesUpdateRequest(List.of( + new MemberNameUpdateRequest("ํ† ๋‹ค๋ง", "ํ† ์Ÿ์ด"), + new MemberNameUpdateRequest("๊ฐ์ž", "๊ณ ๊ตฌ๋งˆ") + )); + + String requestBody = objectMapper.writeValueAsString(memberNameUpdateRequest); + + mockMvc.perform(put("/api/events/{eventId}/members/nameChange", token) + .cookie(EVENT_COOKIE) + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()) + .andDo( + document("updateEventMemberName", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("ํ–‰์‚ฌ ID") + ), + requestCookies( + cookieWithName("eventToken").description("ํ–‰์‚ฌ ๊ด€๋ฆฌ์ž ํ† ํฐ") + ), + requestFields( + fieldWithPath("members").type(JsonFieldType.ARRAY).description("์ˆ˜์ •ํ•  ์ฐธ์—ฌ์ž ๋ชฉ๋ก"), + fieldWithPath("members[].before").type(JsonFieldType.STRING) + .description("์ˆ˜์ • ์ „ ์ฐธ์—ฌ์ž ์ด๋ฆ„"), + fieldWithPath("members[].after").type(JsonFieldType.STRING) + .description("์ˆ˜์ • ํ›„ ์ฐธ์—ฌ์ž ์ด๋ฆ„") + ) + ) + ); + } + + @DisplayName("ํ–‰์‚ฌ ์–ด๋“œ๋ฏผ์ด ๋กœ๊ทธ์ธํ•œ๋‹ค.") + @Test + void loginEvent() throws Exception { + String token = "TOKEN"; + EventLoginRequest eventLoginRequest = new EventLoginRequest("1234"); + String requestBody = objectMapper.writeValueAsString(eventLoginRequest); + given(authService.createToken(token)).willReturn("jwtToken"); + given(authService.getTokenName()).willReturn("eventToken"); + + mockMvc.perform(post("/api/events/{eventId}/login", token) + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(cookie().value("eventToken", "jwtToken")) + .andExpect(status().isOk()) + .andDo( + document("eventLogin", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("ํ–‰์‚ฌ ID") + ), + requestFields( + fieldWithPath("password").type(JsonFieldType.STRING) + .description("ํ–‰์‚ฌ ๋น„๋ฐ€ ๋ฒˆํ˜ธ") + ), + responseCookies( + cookieWithName("eventToken").description("ํ–‰์‚ฌ ๊ด€๋ฆฌ์ž์šฉ ํ† ํฐ") + ) + ) + ); + } + + @DisplayName("ํ–‰์‚ฌ ์ „์ฒด ์•ก์…˜ ์ด๋ ฅ ์กฐํšŒ") + @Test + void findActions() throws Exception { + String token = "TOKEN"; + List<ActionAppResponse> actionAppResponses = List.of( + new ActionAppResponse(1L, "๋ง์ตธ", null, 1L, ActionType.IN), + new ActionAppResponse(2L, "์กฑ๋ฐœ", 100L, 2L, ActionType.BILL), + new ActionAppResponse(3L, "์ธ์ƒ๋„ค์ปท", 1000L, 3L, ActionType.BILL), + new ActionAppResponse(4L, "๋ง์ตธ", null, 4L, ActionType.OUT) + ); + given(eventService.findActions(token)).willReturn(actionAppResponses); + + mockMvc.perform(get("/api/events/{eventId}/actions", token) + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.steps[0].type").value(equalTo("IN"))) + .andExpect(jsonPath("$.steps[0].stepName").value(equalTo("0์ฐจ"))) + .andExpect(jsonPath("$.steps[0].members[0]").value(equalTo("๋ง์ตธ"))) + .andExpect(jsonPath("$.steps[0].actions[0].actionId").value(equalTo(1))) + .andExpect(jsonPath("$.steps[0].actions[0].name").value(equalTo("๋ง์ตธ"))) + .andExpect(jsonPath("$.steps[0].actions[0].price").value(equalTo(null))) + .andExpect(jsonPath("$.steps[0].actions[0].sequence").value(equalTo(1))) + + .andExpect(jsonPath("$.steps[1].type").value(equalTo("BILL"))) + .andExpect(jsonPath("$.steps[1].stepName").value(equalTo("1์ฐจ"))) + .andExpect(jsonPath("$.steps[1].members[0]").value(equalTo("๋ง์ตธ"))) + .andExpect(jsonPath("$.steps[1].actions[0].actionId").value(equalTo(2))) + .andExpect(jsonPath("$.steps[1].actions[0].name").value(equalTo("์กฑ๋ฐœ"))) + .andExpect(jsonPath("$.steps[1].actions[0].price").value(equalTo(100))) + .andExpect(jsonPath("$.steps[1].actions[0].sequence").value(equalTo(2))) + + .andExpect(jsonPath("$.steps[1].actions[1].actionId").value(equalTo(3))) + .andExpect(jsonPath("$.steps[1].actions[1].name").value(equalTo("์ธ์ƒ๋„ค์ปท"))) + .andExpect(jsonPath("$.steps[1].actions[1].price").value(equalTo(1000))) + .andExpect(jsonPath("$.steps[1].actions[1].sequence").value(equalTo(3))) + + .andExpect(jsonPath("$.steps[2].type").value(equalTo("OUT"))) + .andExpect(jsonPath("$.steps[2].stepName").value(equalTo("1์ฐจ"))) + .andExpect(jsonPath("$.steps[2].actions[0].actionId").value(equalTo(4))) + .andExpect(jsonPath("$.steps[2].actions[0].name").value(equalTo("๋ง์ตธ"))) + .andExpect(jsonPath("$.steps[2].actions[0].price").value(equalTo(null))) + .andExpect(jsonPath("$.steps[2].actions[0].sequence").value(equalTo(4))) + + .andDo( + document("findActions", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("ํ–‰์‚ฌ ID") + ), + responseFields( + fieldWithPath("steps[].stepName").type(JsonFieldType.STRING) + .description("์Šคํƒญ ์ด๋ฆ„"), + fieldWithPath("steps[].type").type(JsonFieldType.STRING) + .description("์•ก์…˜ ์œ ํ˜• [BILL, IN, OUT]"), + fieldWithPath("steps[].members").type(JsonFieldType.ARRAY) + .description("ํ•ด๋‹น step์— ์ฐธ์—ฌํ•œ ์ฐธ์—ฌ์ž ๋ชฉ๋ก"), + fieldWithPath("steps[].actions[].actionId").type(JsonFieldType.NUMBER) + .description("์•ก์…˜ ID"), + fieldWithPath("steps[].actions[].name").type(JsonFieldType.STRING) + .description("์ฐธ์—ฌ์ž ์•ก์…˜์ผ ๊ฒฝ์šฐ ์ฐธ์—ฌ์ž ์ด๋ฆ„, ์ง€์ถœ ์•ก์…˜์ผ ๊ฒฝ์šฐ ์ง€์ถœ ๋‚ด์—ญ ์ด๋ฆ„"), + fieldWithPath("steps[].actions[].price").type(JsonFieldType.NUMBER).optional() + .description("์ฐธ์—ฌ์ž ์•ก์…˜์ผ ๊ฒฝ์šฐ null, ์ง€์ถœ ์•ก์…˜์ผ ๊ฒฝ์šฐ ์ง€์ถœ ๊ธˆ์•ก"), + fieldWithPath("steps[].actions[].sequence").type(JsonFieldType.NUMBER) + .description("์•ก์…˜ ์ˆœ์„œ"), + fieldWithPath("steps[].actions[].isFixed").type(JsonFieldType.BOOLEAN) + .description("์ง€์ถœ ๋‚ด์—ญ์˜ ๋ฉค๋ฒ„๋ณ„ ๊ณ ์ • ์ง€์ถœ ๊ธˆ์•ก ์ƒ์„ฑ ์—ฌ๋ถ€") + ) + ) + ); + } + + @DisplayName("ํ–‰์‚ฌ ์ „์ฒด ์•ก์…˜ ์ด๋ ฅ ์กฐํšŒ v2") + @Test + void findActions2() throws Exception { + String token = "TOKEN"; + List<ActionAppResponse> actionAppResponses = List.of( + new ActionAppResponse(1L, "๋ง์ตธ", null, 1L, ActionType.IN), + new ActionAppResponse(2L, "์กฑ๋ฐœ", 100L, 2L, ActionType.BILL), + new ActionAppResponse(3L, "์ธ์ƒ๋„ค์ปท", 1000L, 3L, ActionType.BILL), + new ActionAppResponse(4L, "๋ง์ตธ", null, 4L, ActionType.OUT) + ); + given(eventService.findActions(token)).willReturn(actionAppResponses); + + mockMvc.perform(get("/api/events/{eventId}/actions/v2", token) + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.actions[0].actionId").value(equalTo(1))) + .andExpect(jsonPath("$.actions[0].name").value(equalTo("๋ง์ตธ"))) + .andExpect(jsonPath("$.actions[0].price").value(equalTo(null))) + .andExpect(jsonPath("$.actions[0].sequence").value(equalTo(1))) + .andExpect(jsonPath("$.actions[0].type").value(equalTo("IN"))) + + .andExpect(jsonPath("$.actions[1].actionId").value(equalTo(2))) + .andExpect(jsonPath("$.actions[1].name").value(equalTo("์กฑ๋ฐœ"))) + .andExpect(jsonPath("$.actions[1].price").value(equalTo(100))) + .andExpect(jsonPath("$.actions[1].sequence").value(equalTo(2))) + .andExpect(jsonPath("$.actions[1].type").value(equalTo("BILL"))) + + .andExpect(jsonPath("$.actions[2].actionId").value(equalTo(3))) + .andExpect(jsonPath("$.actions[2].name").value(equalTo("์ธ์ƒ๋„ค์ปท"))) + .andExpect(jsonPath("$.actions[2].price").value(equalTo(1000))) + .andExpect(jsonPath("$.actions[2].sequence").value(equalTo(3))) + .andExpect(jsonPath("$.actions[2].type").value(equalTo("BILL"))) + + .andExpect(jsonPath("$.actions[3].actionId").value(equalTo(4))) + .andExpect(jsonPath("$.actions[3].name").value(equalTo("๋ง์ตธ"))) + .andExpect(jsonPath("$.actions[3].price").value(equalTo(null))) + .andExpect(jsonPath("$.actions[3].sequence").value(equalTo(4))) + .andExpect(jsonPath("$.actions[3].type").value(equalTo("OUT"))) + + .andDo( + document("findActions", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("ํ–‰์‚ฌ ID") + ), + responseFields( + fieldWithPath("actions[].actionId").type(JsonFieldType.NUMBER) + .description("์•ก์…˜ ID"), + fieldWithPath("actions[].name").type(JsonFieldType.STRING) + .description("์ฐธ์—ฌ์ž ์•ก์…˜์ผ ๊ฒฝ์šฐ ์ฐธ์—ฌ์ž ์ด๋ฆ„, ์ง€์ถœ ์•ก์…˜์ผ ๊ฒฝ์šฐ ์ง€์ถœ ๋‚ด์—ญ ์ด๋ฆ„"), + fieldWithPath("actions[].price").type(JsonFieldType.NUMBER).optional() + .description("์ฐธ์—ฌ์ž ์•ก์…˜์ผ ๊ฒฝ์šฐ null, ์ง€์ถœ ์•ก์…˜์ผ ๊ฒฝ์šฐ ์ง€์ถœ ๊ธˆ์•ก"), + fieldWithPath("actions[].sequence").type(JsonFieldType.NUMBER) + .description("์•ก์…˜ ์ˆœ์„œ"), + fieldWithPath("actions[].type").type(JsonFieldType.STRING) + .description("์•ก์…˜ ํƒ€์ž…") + ) + ) + ); + } + + @DisplayName("ํ–‰์‚ฌ ์–ด๋“œ๋ฏผ ๊ถŒํ•œ์„ ํ™•์ธํ•œ๋‹ค.") + @Test + void authenticateTest() throws Exception { + String token = "TOKEN"; + mockMvc.perform(post("/api/events/{eventId}/auth", token) + .cookie(EVENT_COOKIE)) + .andDo(print()) + .andExpect(status().isOk()) + + .andDo( + document("authenticateEvent", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("ํ–‰์‚ฌ ID") + ), + requestCookies( + cookieWithName("eventToken").description("ํ–‰์‚ฌ ๊ด€๋ฆฌ์ž ํ† ํฐ").optional() + ) + ) + ); + } +} diff --git a/server/src/test/java/server/haengdong/docs/MemberActionControllerDocsTest.java b/server/src/test/java/server/haengdong/docs/MemberActionControllerDocsTest.java new file mode 100644 index 000000000..afd766c8f --- /dev/null +++ b/server/src/test/java/server/haengdong/docs/MemberActionControllerDocsTest.java @@ -0,0 +1,157 @@ +package server.haengdong.docs; + +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName; +import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static server.haengdong.support.fixture.Fixture.EVENT_COOKIE; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; +import server.haengdong.application.MemberActionService; +import server.haengdong.application.response.CurrentMemberAppResponse; +import server.haengdong.presentation.MemberActionController; +import server.haengdong.presentation.request.MemberActionsSaveRequest; + +public class MemberActionControllerDocsTest extends RestDocsSupport { + + private final MemberActionService memberActionService = mock(MemberActionService.class); + + @Override + protected Object initController() { + return new MemberActionController(memberActionService); + } + + @DisplayName("์ฐธ์—ฌ์ž ํ–‰๋™์„ ์ถ”๊ฐ€ํ•œ๋‹ค.") + @Test + void saveMemberActionTest() throws Exception { + MemberActionsSaveRequest memberActionsSaveRequest = new MemberActionsSaveRequest( + List.of("์›จ๋””", "์†Œํ•˜", "ํ† ๋‹ค๋ฆฌ", "์ฟ ํ‚ค"), "IN"); + + String requestBody = objectMapper.writeValueAsString(memberActionsSaveRequest); + + mockMvc.perform(post("/api/events/{eventId}/member-actions", "๋ง์ตธํ† ํฐ") + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody) + .cookie(EVENT_COOKIE)) + .andDo(print()) + .andExpect(status().isOk()) + .andDo( + document("createMemberAction", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("ํ–‰์‚ฌ ID") + ), + requestCookies( + cookieWithName("eventToken").description("ํ† ํฐ ํ† ํฐ") + ), + requestFields( + fieldWithPath("members").type(JsonFieldType.ARRAY) + .description("์•ก์…˜ ๋Œ€์ƒ ์ฐธ์—ฌ์ž ๋ชฉ๋ก"), + fieldWithPath("status").type(JsonFieldType.STRING) + .description("์ฐธ์—ฌ์ž ์•ก์…˜ ์ƒํƒœ [IN(๋Šฆ์ฐธ), OUT(ํƒˆ์ฃผ)]") + ) + ) + ); + } + + @DisplayName("ํ˜„์žฌ ์ฐธ์—ฌ ์ธ์›์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.") + @Test + void getCurrentMembers() throws Exception { + List<CurrentMemberAppResponse> currentMemberAppResponses = List.of( + new CurrentMemberAppResponse("์†Œํ•˜"), new CurrentMemberAppResponse("ํ† ๋‹ค๋ฆฌ")); + + given(memberActionService.getCurrentMembers(any())).willReturn(currentMemberAppResponses); + + mockMvc.perform(get("/api/events/{eventId}/members/current", "๋ง์ตธํ† ํฐ") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.memberNames[0]").value(equalTo("์†Œํ•˜"))) + .andExpect(jsonPath("$.memberNames[1]").value(equalTo("ํ† ๋‹ค๋ฆฌ"))) + .andDo( + document("getCurrentMembers", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("ํ–‰์‚ฌ ID") + ), + responseFields( + fieldWithPath("memberNames").type(JsonFieldType.ARRAY) + .description("ํ˜„์žฌ ํƒˆ์ฃผ ๊ฐ€๋Šฅํ•œ ์ฐธ์—ฌ ์ธ์› ์ด๋ฆ„ ๋ชฉ๋ก") + ) + ) + ); + } + + @DisplayName("์ด๋ฒคํŠธ์— ์†ํ•œ ๋ฉค๋ฒ„ ์•ก์…˜์„ ์‚ญ์ œํ•˜๋ฉด ์ดํ›„์— ๊ธฐ๋ก๋œ ํ•ด๋‹น ์ฐธ์—ฌ์ž์˜ ๋ชจ๋“  ๋ฉค๋ฒ„ ์•ก์…˜์„ ์‚ญ์ œํ•œ๋‹ค.") + @Test + void deleteMemberAction() throws Exception { + String eventId = "๋ง์ตธํ† ํฐ"; + Long actionId = 2L; + + mockMvc.perform(delete("/api/events/{eventId}/member-actions/{actionId}", eventId, actionId) + .cookie(EVENT_COOKIE)) + .andDo(print()) + .andExpect(status().isOk()) + .andDo( + document("deleteMemberAction", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("ํ–‰์‚ฌ ID"), + parameterWithName("actionId").description("์•ก์…˜ ID") + ), + requestCookies( + cookieWithName("eventToken").description("ํ–‰์‚ฌ ๊ด€๋ฆฌ์ž์šฉ ํ† ํฐ") + ) + ) + ); + } + + @DisplayName("ํ–‰์‚ฌ์˜ ์ „์ฒด ์ฐธ์—ฌ์ž ์ค‘์—์„œ ํŠน์ • ์ฐธ์—ฌ์ž์˜ ๋งด๋ฒ„ ์•ก์…˜์„ ์ „๋ถ€ ์‚ญ์ œํ•œ๋‹ค.") + @Test + void deleteMember() throws Exception { + String eventId = "๋ง์ตธํ† ํฐ"; + String memberName = "ํ–‰๋™๋Œ€์žฅ"; + + mockMvc.perform(delete("/api/events/{eventId}/members/{memberName}", eventId, memberName) + .cookie(EVENT_COOKIE)) + .andDo(print()) + .andExpect(status().isOk()) + .andDo( + document("deleteAllMemberActionByName", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("ํ–‰์‚ฌ ID"), + parameterWithName("memberName").description("ํ–‰์‚ฌ ์ฐธ์—ฌ์ž ์ด๋ฆ„") + ), + requestCookies( + cookieWithName("eventToken").description("ํ–‰์‚ฌ ๊ด€๋ฆฌ์ž์šฉ ํ† ํฐ") + ) + ) + ); + } +} diff --git a/server/src/test/java/server/haengdong/docs/RestDocsSupport.java b/server/src/test/java/server/haengdong/docs/RestDocsSupport.java new file mode 100644 index 000000000..3e6901ba8 --- /dev/null +++ b/server/src/test/java/server/haengdong/docs/RestDocsSupport.java @@ -0,0 +1,28 @@ +package server.haengdong.docs; + +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.restdocs.RestDocumentationContextProvider; +import org.springframework.restdocs.RestDocumentationExtension; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +@ExtendWith({RestDocumentationExtension.class}) +abstract class RestDocsSupport { + + protected MockMvc mockMvc; + + protected ObjectMapper objectMapper = new ObjectMapper(); + + @BeforeEach + void setUp(RestDocumentationContextProvider restDocumentation) { + this.mockMvc = MockMvcBuilders.standaloneSetup(initController()) + .apply(documentationConfiguration(restDocumentation)) + .build(); + } + + protected abstract Object initController(); +} diff --git a/server/src/test/java/server/haengdong/domain/action/ActionTest.java b/server/src/test/java/server/haengdong/domain/action/ActionTest.java new file mode 100644 index 000000000..6ff25479c --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/action/ActionTest.java @@ -0,0 +1,31 @@ +package server.haengdong.domain.action; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import server.haengdong.domain.event.Event; +import server.haengdong.support.fixture.Fixture; + +class ActionTest { + + @DisplayName("์•ก์…˜์˜ ์ดˆ๊ธฐ ์ˆœ์„œ๋ฒˆํ˜ธ๋Š” 1์ด๋‹ค.") + @Test + void createFirst() { + Event event = Fixture.EVENT1; + Action action = Action.createFirst(event); + + assertThat(action.getSequence()).isOne(); + } + + @DisplayName("ํ˜„์žฌ ์•ก์…˜์˜ ๋‹ค์Œ ์•ก์…˜์˜ ์ˆœ์„œ๋Š” 1๋งŒํผ ์ฆ๊ฐ€ํ•œ๋‹ค.") + @Test + void next() { + Event event = Fixture.EVENT1; + Action action = new Action(event, 2L); + + Action nextAction = action.next(); + + assertThat(nextAction.getSequence()).isEqualTo(3L); + } +} diff --git a/server/src/test/java/server/haengdong/domain/action/BillActionTest.java b/server/src/test/java/server/haengdong/domain/action/BillActionTest.java new file mode 100644 index 000000000..ba1ab36f2 --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/action/BillActionTest.java @@ -0,0 +1,89 @@ +package server.haengdong.domain.action; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; +import static server.haengdong.support.fixture.Fixture.BILL_ACTION; +import static server.haengdong.support.fixture.Fixture.EVENT1; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import server.haengdong.domain.event.Event; +import server.haengdong.exception.HaengdongException; + +class BillActionTest { + + @DisplayName("์ง€์ถœ ๋‚ด์—ญ ์ œ๋ชฉ์˜ ์•ž๋’ค ๊ณต๋ฐฑ์„ ์ œ๊ฑฐํ•œ ๊ธธ์ด๊ฐ€ 1 ~ 30์ž๊ฐ€ ์•„๋‹ˆ๋ฉด ์ง€์ถœ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์—†๋‹ค.") + @ParameterizedTest + @ValueSource(strings = {"", " ", "1234567890123456789012345678901"}) + void validateTitle(String title) { + Event event = EVENT1; + Action action = new Action(event, 1L); + Long price = 100L; + + assertThatThrownBy(() -> new BillAction(action, title, price)) + .isInstanceOf(HaengdongException.class) + .hasMessage("์•ž๋’ค ๊ณต๋ฐฑ์„ ์ œ๊ฑฐํ•œ ์ง€์ถœ ๋‚ด์—ญ ์ œ๋ชฉ์€ 1 ~ 30์ž์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค."); + } + + @DisplayName("๊ธˆ์•ก์ด 10,000,000 ์ดํ•˜์˜ ์ž์—ฐ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ฉด ์ง€์ถœ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์—†๋‹ค.") + @ParameterizedTest + @ValueSource(longs = {0, 10_000_001, 20_000_000}) + void validatePrice(long price) { + Event event = EVENT1; + Action action = new Action(event, 1L); + String title = "title"; + + assertThatThrownBy(() -> new BillAction(action, title, price)) + .isInstanceOf(HaengdongException.class) + .hasMessage("์ง€์ถœ ๊ธˆ์•ก์€ 10,000,000 ์ดํ•˜์˜ ์ž์—ฐ์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค."); + } + + @DisplayName("์ง€์ถœ ๋‚ด์—ญ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ƒ์„ฑํ•œ๋‹ค.") + @Test + void createBillAction() { + Event event = EVENT1; + Action action = new Action(event, 1L); + String title = "title"; + Long price = 1_000L; + + BillAction billAction = new BillAction(action, title, price); + + assertAll( + () -> assertThat(billAction.getAction()).isEqualTo(action), + () -> assertThat(billAction.getTitle()).isEqualTo(title), + () -> assertThat(billAction.getPrice()).isEqualTo(price) + ); + } + + @DisplayName("์ง€์ถœ ์•ก์…˜์— ๋ฉค๋ฒ„๋ณ„ ๊ณ ์ • ๊ธˆ์•ก์ด ์„ค์ •๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.") + @Test + void isFixed1() { + BillAction fixedBillAction = new BillAction(new Action(EVENT1, 1L), "์ธ์ƒ๋„ค์ปท", 2_000L); + + List<BillActionDetail> unfixedBillActionDetails = List.of( + new BillActionDetail(BILL_ACTION, "๊ฐ์ž", 1_000L, false), + new BillActionDetail(BILL_ACTION, "๊ณ ๊ตฌ๋งˆ", 1_000L, false) + ); + fixedBillAction.addDetails(unfixedBillActionDetails); + + assertThat(fixedBillAction.isFixed()).isEqualTo(false); + } + + @DisplayName("์ง€์ถœ ์•ก์…˜์— ๋ฉค๋ฒ„๋ณ„ ๊ณ ์ • ๊ธˆ์•ก์ด ์„ค์ •๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.") + @Test + void isFixed2() { + BillAction fixedBillAction = new BillAction(new Action(EVENT1, 1L), "์ธ์ƒ๋„ค์ปท", 5_000L); + + List<BillActionDetail> unfixedBillActionDetails = List.of( + new BillActionDetail(BILL_ACTION, "๊ฐ์ž", 4_000L, true), + new BillActionDetail(BILL_ACTION, "๊ณ ๊ตฌ๋งˆ", 1_000L, true) + ); + fixedBillAction.addDetails(unfixedBillActionDetails); + + assertThat(fixedBillAction.isFixed()).isEqualTo(true); + } +} diff --git a/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java b/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java new file mode 100644 index 000000000..93148abd3 --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java @@ -0,0 +1,97 @@ +package server.haengdong.domain.action; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static server.haengdong.domain.action.MemberActionStatus.IN; +import static server.haengdong.domain.action.MemberActionStatus.OUT; + +import java.util.List; +import java.util.Set; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import server.haengdong.domain.event.Event; +import server.haengdong.exception.HaengdongException; +import server.haengdong.support.fixture.Fixture; + +class CurrentMembersTest { + + @DisplayName("์ธ์› ๋ณ€๋™ ์ด๋ ฅ์œผ๋กœ ํ˜„์žฌ ์ฐธ์—ฌ ์ธ์›์„ ๊ณ„์‚ฐํ•œ๋‹ค.") + @Test + void of() { + Event event = Fixture.EVENT1; + List<MemberAction> memberActions = List.of( + new MemberAction(new Action(event, 1L), "๋ง์ตธ", IN, 1L), + new MemberAction(new Action(event, 2L), "๋ฐฑํ˜ธ", IN, 1L), + new MemberAction(new Action(event, 3L), "๋ฐฑํ˜ธ", OUT, 1L), + new MemberAction(new Action(event, 4L), "์›จ๋””", IN, 1L) + ); + + CurrentMembers currentMembers = CurrentMembers.of(memberActions); + + assertThat(currentMembers.getMembers()) + .containsExactlyInAnyOrder("๋ง์ตธ", "์›จ๋””"); + } + + @DisplayName("์ธ์› ๋ณ€๋™ ์•ก์…˜์˜ ์ƒํƒœ๊ฐ€ IN์ด๋ฉด ํ˜„์žฌ ์ธ์›์— ์ถ”๊ฐ€ํ•œ๋‹ค.") + @Test + void addMemberAction1() { + CurrentMembers currentMembers = new CurrentMembers(); + Event event = Fixture.EVENT1; + MemberAction memberAction = new MemberAction(new Action(event, 1L), "์›จ๋””", IN, 1L); + + CurrentMembers addedCurrentMembers = currentMembers.addMemberAction(memberAction); + Set<String> members = addedCurrentMembers.getMembers(); + + assertThat(members).hasSize(1) + .containsExactly("์›จ๋””"); + } + + @DisplayName("์ธ์› ๋ณ€๋™ ์•ก์…˜์˜ ์ƒํƒœ๊ฐ€ OUT์ด๋ฉด ํ˜„์žฌ ์ธ์›์—์„œ ์ œ์™ธํ•œ๋‹ค.") + @Test + void addMemberAction2() { + Event event = Fixture.EVENT1; + MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "์›จ๋””", IN, 1L); + CurrentMembers currentMembers = new CurrentMembers().addMemberAction(memberAction1); + MemberAction memberAction2 = new MemberAction(new Action(event, 1L), "์›จ๋””", OUT, 1L); + + CurrentMembers addedCurrentMembers = currentMembers.addMemberAction(memberAction2); + + assertThat(addedCurrentMembers.getMembers()).hasSize(0); + } + + @DisplayName("ํ˜„์žฌ ์ฐธ์—ฌ์ค‘์ธ ์ธ์›์€ ๋‚˜๊ฐˆ ์ˆ˜ ์žˆ๋‹ค.") + @Test + void validate1() { + CurrentMembers currentMembers = new CurrentMembers(Set.of("ํ† ๋‹ค๋ฆฌ")); + + assertThatCode(() -> currentMembers.validate("ํ† ๋‹ค๋ฆฌ", OUT)) + .doesNotThrowAnyException(); + } + + @DisplayName("ํ˜„์žฌ ์ฐธ์—ฌ์ค‘์ด์ง€ ์•Š์€ ์ธ์›์€ ๋“ค์–ด์˜ฌ ์ˆ˜ ์žˆ๋‹ค.") + @Test + void validate2() { + CurrentMembers currentMembers = new CurrentMembers(Set.of("์ฟ ํ‚ค")); + + assertThatCode(() -> currentMembers.validate("ํ† ๋‹ค๋ฆฌ", IN)) + .doesNotThrowAnyException(); + } + + @DisplayName("ํ˜„์žฌ ์ฐธ์—ฌ์ค‘์ธ ์ธ์›์€ ๋“ค์–ด์˜ฌ ์ˆ˜ ์—†๋‹ค.") + @Test + void validate3() { + CurrentMembers currentMembers = new CurrentMembers(Set.of("ํ† ๋‹ค๋ฆฌ")); + + assertThatCode(() -> currentMembers.validate("ํ† ๋‹ค๋ฆฌ", IN)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("ํ˜„์žฌ ์ฐธ์—ฌ์ค‘์ด์ง€ ์•Š์€ ์ธ์›์€ ๋‚˜๊ฐˆ ์ˆ˜ ์—†๋‹ค.") + @Test + void validate4() { + CurrentMembers currentMembers = new CurrentMembers(Set.of("์ฟ ํ‚ค")); + + assertThatCode(() -> currentMembers.validate("ํ† ๋‹ค๋ฆฌ", OUT)) + .isInstanceOf(HaengdongException.class); + } +} diff --git a/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java b/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java new file mode 100644 index 000000000..02070a537 --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java @@ -0,0 +1,56 @@ +package server.haengdong.domain.action; + +import static org.assertj.core.api.Assertions.assertThat; +import static server.haengdong.domain.action.MemberActionStatus.IN; +import static server.haengdong.domain.action.MemberActionStatus.OUT; +import static server.haengdong.support.fixture.Fixture.BILL_ACTION; + +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import server.haengdong.domain.event.Event; +import server.haengdong.support.fixture.Fixture; + +class MemberBillReportTest { + + @DisplayName("์•ก์…˜ ๋ชฉ๋ก์œผ๋กœ ์ฐธ๊ฐ€์ž ์ •์‚ฐ ๋ฆฌํฌํŠธ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.") + @Test + void createByActions() { + Event event = Fixture.EVENT1; + List<BillAction> billActions = List.of( + new BillAction(new Action(event, 4L), "๋ฝ•์กฑ", 60_000L), + new BillAction(new Action(event, 7L), "์ธ์ƒ๋„ค์ปท", 20_000L) + ); + billActions.get(0).addDetails( + List.of( + new BillActionDetail(BILL_ACTION, "์†Œํ•˜", 10_000L, false), + new BillActionDetail(BILL_ACTION, "๊ฐ์ž", 40_000L, true), + new BillActionDetail(BILL_ACTION, "์ฟ ํ‚ค", 10_000L, false) + ) + ); + billActions.get(1).addDetails( + List.of( + new BillActionDetail(BILL_ACTION, "์†Œํ•˜", 5_000L, true), + new BillActionDetail(BILL_ACTION, "์ฟ ํ‚ค", 15_000L, true) + ) + ); + List<MemberAction> memberActions = List.of( + new MemberAction(new Action(event, 1L), "์†Œํ•˜", IN, 1L), + new MemberAction(new Action(event, 2L), "๊ฐ์ž", IN, 1L), + new MemberAction(new Action(event, 3L), "์ฟ ํ‚ค", IN, 1L), + new MemberAction(new Action(event, 5L), "๊ฐ์ž", OUT, 2L) + ); + + MemberBillReport memberBillReport = MemberBillReport.createByActions(billActions, memberActions); + + assertThat(memberBillReport.getReports()) + .containsAllEntriesOf( + Map.of( + "๊ฐ์ž", 40_000L, + "์ฟ ํ‚ค", 25_000L, + "์†Œํ•˜", 15_000L + ) + ); + } +} diff --git a/server/src/test/java/server/haengdong/domain/event/EventTest.java b/server/src/test/java/server/haengdong/domain/event/EventTest.java new file mode 100644 index 000000000..12c0c0569 --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/event/EventTest.java @@ -0,0 +1,65 @@ +package server.haengdong.domain.event; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import server.haengdong.exception.HaengdongException; + +class EventTest { + + @DisplayName("๊ณต๋ฐฑ ๋ฌธ์ž๊ฐ€ ์—ฐ์†๋˜์ง€ ์•Š๊ณ , ์ด๋ฆ„์ด 2์ž ์ด์ƒ 20์ž ์ดํ•˜์ธ ํ–‰์‚ฌ๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.") + @ParameterizedTest + @ValueSource(strings = {"12", "12345678901234567890", "๊ณต ๋ฐฑ", " ๊ณต๋ฐฑ", "๊ณต๋ฐฑ ", " ๊ณต ๋ฐฑ "}) + void createSuccessTest(String eventName) { + assertThatCode(() -> new Event(eventName, "1234", "TEST_TOKEN")) + .doesNotThrowAnyException(); + } + + @DisplayName("๊ณต๋ฐฑ ๋ฌธ์ž๊ฐ€ ์—ฐ์†๋˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @ParameterizedTest + @ValueSource(strings = {" ๊ณต๋ฐฑ", "๊ณต๋ฐฑ ", "๊ณต๋ฐฑ ์—ฐ์†", "๊ณต ๋ฐฑ"}) + void createFailTest1(String eventName) { + assertThatCode(() -> new Event(eventName, "1234", "TEST_TOKEN")) + .isInstanceOf(HaengdongException.class) + .hasMessage(String.format("ํ–‰์‚ฌ ์ด๋ฆ„์—๋Š” ๊ณต๋ฐฑ ๋ฌธ์ž๊ฐ€ ์—ฐ์†๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ž…๋ ฅํ•œ ์ด๋ฆ„ : %s", eventName)); + } + + @DisplayName("์ด๋ฆ„์ด 1์ž ๋ฏธ๋งŒ์ด๊ฑฐ๋‚˜ 20์ž ์ดˆ๊ณผ์ธ ๊ฒฝ์šฐ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.") + @ParameterizedTest + @ValueSource(strings = {"", " ", "123456789012345678901"}) + void createFilTest2(String eventName) { + assertThatCode(() -> new Event(eventName, "1234", "TEST_TOKEN")) + .isInstanceOf(HaengdongException.class) + .hasMessage(String.format("ํ–‰์‚ฌ ์ด๋ฆ„์€ 1์ž ์ด์ƒ 20์ž ์ดํ•˜๋งŒ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ž…๋ ฅํ•œ ์ด๋ฆ„ ๊ธธ์ด : %d", eventName.length())); + } + + @DisplayName("๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” 4์ž๋ฆฌ ์ˆซ์ž ์ž…๋‹ˆ๋‹ค.") + @ParameterizedTest + @ValueSource(strings = {"1", "12", "123", "12345", "adgd"}) + void validatePassword(String password) { + assertThatCode(() -> new Event("์ด๋ฆ„", password, "TEST_TOKEN")) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ๋‹ค๋ฅธ์ง€ ๊ฒ€์ฆํ•œ๋‹ค.") + @Test + void isNotSamePassword() { + String rawPassword = "1234"; + Event event = new Event("์ด๋ฆ„", rawPassword, "TEST_TOKEN"); + + assertThat(event.isPasswordMismatch(rawPassword)).isFalse(); + } + + @DisplayName("๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ๋‹ค๋ฅธ์ง€ ๊ฒ€์ฆํ•œ๋‹ค.") + @Test + void isNotSamePassword1() { + String rawPassword = "1234"; + Event event = new Event("์ด๋ฆ„", "5678", "TEST_TOKEN"); + + assertThat(event.isPasswordMismatch(rawPassword)).isTrue(); + } +} diff --git a/server/src/test/java/server/haengdong/domain/event/PasswordTest.java b/server/src/test/java/server/haengdong/domain/event/PasswordTest.java new file mode 100644 index 000000000..c504d3aa2 --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/event/PasswordTest.java @@ -0,0 +1,19 @@ +package server.haengdong.domain.event; + +import static org.assertj.core.api.Assertions.assertThatCode; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import server.haengdong.exception.HaengdongException; + +class PasswordTest { + + @DisplayName("๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” 4์ž๋ฆฌ ์ˆซ์ž ์ž…๋‹ˆ๋‹ค.") + @ParameterizedTest + @ValueSource(strings = {"1", "12", "123", "12345", "adgd"}) + void validatePassword(String rawPassword) { + assertThatCode(() -> new Password(rawPassword)) + .isInstanceOf(HaengdongException.class); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java new file mode 100644 index 000000000..1de5889b5 --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java @@ -0,0 +1,36 @@ +package server.haengdong.presentation; + +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import server.haengdong.application.response.MemberBillReportAppResponse; + +class ActionControllerTest extends ControllerTestSupport { + + @DisplayName("์ฐธ์—ฌ์ž๋ณ„ ์ •์‚ฐ ํ˜„ํ™ฉ์„ ์กฐํšŒํ•œ๋‹ค.") + @Test + void getMemberBillReports() throws Exception { + List<MemberBillReportAppResponse> memberBillReportAppResponses = List.of( + new MemberBillReportAppResponse("์†Œํ•˜", 20_000L), new MemberBillReportAppResponse("ํ† ๋‹ค๋ฆฌ", 200_000L)); + + given(actionService.getMemberBillReports(any())).willReturn(memberBillReportAppResponses); + + mockMvc.perform(get("/api/events/{eventId}/actions/reports", "๋ง์ตธํ† ํฐ") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].name").value(equalTo("์†Œํ•˜"))) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].price").value(equalTo(20_000))) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].name").value(equalTo("ํ† ๋‹ค๋ฆฌ"))) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].price").value(equalTo(200_000))); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java new file mode 100644 index 000000000..4420e369c --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java @@ -0,0 +1,97 @@ +package server.haengdong.presentation; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doThrow; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; +import server.haengdong.presentation.request.BillActionSaveRequest; +import server.haengdong.presentation.request.BillActionUpdateRequest; +import server.haengdong.presentation.request.BillActionsSaveRequest; + +class BillActionControllerTest extends ControllerTestSupport { + + @DisplayName("์ง€์ถœ ๋‚ด์—ญ์„ ์ƒ์„ฑํ•œ๋‹ค.") + @Test + void saveAllBillAction() throws Exception { + BillActionsSaveRequest request = new BillActionsSaveRequest( + List.of( + new BillActionSaveRequest("๋ฝ•์กฑ", 10_000L), + new BillActionSaveRequest("์ธ์ƒ๋งฅ์ฃผ", 10_000L) + ) + ); + String requestBody = objectMapper.writeValueAsString(request); + String eventId = "์ฟ ํ‚คํ† ํฐ"; + + mockMvc.perform(post("/api/events/{eventId}/bill-actions", eventId) + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()); + } + + @DisplayName("title์ด ๋น„์–ด ์žˆ๋Š” ๊ฒฝ์šฐ ์ง€์ถœ ๋‚ด์—ญ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์—†๋‹ค.") + @Test + void saveAllBillAction1() throws Exception { + BillActionsSaveRequest request = new BillActionsSaveRequest( + List.of( + new BillActionSaveRequest("", 10_000L), + new BillActionSaveRequest("์ธ์ƒ๋งฅ์ฃผ", 10_000L) + ) + ); + String requestBody = objectMapper.writeValueAsString(request); + String eventId = "์†Œํ•˜ํ† ํฐ"; + + mockMvc.perform(post("/api/events/{eventId}/bill-actions", eventId) + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isBadRequest()); + } + + @DisplayName("์ง€์ถœ ์•ก์…˜์„ ์ˆ˜์ •ํ•œ๋‹ค.") + @Test + void updateBillAction() throws Exception { + BillActionUpdateRequest request = new BillActionUpdateRequest("๋ฝ•์กฑ", 10_000L); + + String requestBody = objectMapper.writeValueAsString(request); + String eventId = "์›จ๋””ํ† ํฐ"; + + mockMvc.perform(put("/api/events/{eventId}/bill-actions/{actionId}", eventId, 1L) + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()); + } + + @DisplayName("์ง€์ถœ ๋‚ด์—ญ์„ ์‚ญ์ œํ•œ๋‹ค.") + @Test + void deleteBillAction() throws Exception { + String eventId = "ํ† ๋‹ค๋ฆฌํ† ํฐ"; + + mockMvc.perform(delete("/api/events/{eventId}/bill-actions/{actionId}", eventId, 1)) + .andDo(print()) + .andExpect(status().isOk()); + } + + @DisplayName("์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ–‰์‚ฌ์— ๋Œ€ํ•œ ์ง€์ถœ ๋‚ด์—ญ์„ ์‚ญ์ œํ•  ์ˆ˜ ์—†๋‹ค.") + @Test + void deleteBillAction1() throws Exception { + String eventId = "์ด์ƒํ•ดํ† ํฐ"; + doThrow(new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)) + .when(billActionService).deleteBillAction(any(String.class), any(Long.class)); + + mockMvc.perform(delete("/api/events/{eventId}/bill-actions/{actionId}", eventId, 1)) + .andDo(print()) + .andExpect(status().isBadRequest()); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/BillActionDetailControllerTest.java b/server/src/test/java/server/haengdong/presentation/BillActionDetailControllerTest.java new file mode 100644 index 000000000..6b595ee27 --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/BillActionDetailControllerTest.java @@ -0,0 +1,56 @@ +package server.haengdong.presentation; + +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import server.haengdong.application.response.BillActionDetailAppResponse; +import server.haengdong.application.response.BillActionDetailsAppResponse; +import server.haengdong.presentation.request.BillActionDetailUpdateRequest; +import server.haengdong.presentation.request.BillActionDetailsUpdateRequest; + +class BillActionDetailControllerTest extends ControllerTestSupport { + + @DisplayName("์ฐธ์—ฌ์ž๋ณ„ ์ง€์ถœ ๊ธˆ์•ก์„ ์กฐํšŒํ•œ๋‹ค.") + @Test + void findBillActionDetails() throws Exception { + BillActionDetailsAppResponse appResponse = new BillActionDetailsAppResponse( + List.of(new BillActionDetailAppResponse("ํ† ๋‹ค๋ฆฌ", 1000L, false))); + given(billActionDetailService.findBillActionDetails(anyString(), anyLong())) + .willReturn(appResponse); + + mockMvc.perform(get("/api/events/{eventId}/bill-actions/{actionId}/fixed", "TOKEN", 1L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.members").isArray()) + .andExpect(jsonPath("$.members[0].name").value("ํ† ๋‹ค๋ฆฌ")) + .andExpect(jsonPath("$.members[0].price").value(1000L)); + } + + @DisplayName("์ฐธ์—ฌ์ž๋ณ„ ์ง€์ถœ ๊ธˆ์•ก์„ ์ˆ˜์ •ํ•œ๋‹ค.") + @Test + void updateBillActionDetailsTest() throws Exception { + List<BillActionDetailUpdateRequest> billActionDetailUpdateRequests = List.of( + new BillActionDetailUpdateRequest("์†Œํ•˜", 10000L, true), + new BillActionDetailUpdateRequest("์›จ๋””", 20000L, true) + ); + BillActionDetailsUpdateRequest request = new BillActionDetailsUpdateRequest( + billActionDetailUpdateRequests); + + String json = objectMapper.writeValueAsString(request); + + mockMvc.perform(put("/api/events/{eventId}/bill-actions/{actionId}/fixed", "TOKEN", 1L) + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andDo(print()) + .andExpect(status().isOk()); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/ControllerTestSupport.java b/server/src/test/java/server/haengdong/presentation/ControllerTestSupport.java new file mode 100644 index 000000000..46489b1a5 --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/ControllerTestSupport.java @@ -0,0 +1,53 @@ +package server.haengdong.presentation; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.FilterType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import server.haengdong.application.ActionService; +import server.haengdong.application.AuthService; +import server.haengdong.application.BillActionDetailService; +import server.haengdong.application.BillActionService; +import server.haengdong.application.EventService; +import server.haengdong.application.MemberActionService; + +@WebMvcTest( + controllers = { + EventController.class, + ActionController.class, + BillActionController.class, + MemberActionController.class, + BillActionDetailController.class + }, + excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {WebMvcConfigurer.class})} +) +abstract class ControllerTestSupport { + + @Autowired + protected MockMvc mockMvc; + + @Autowired + protected ObjectMapper objectMapper; + + @MockBean + protected EventService eventService; + + @MockBean + protected AuthService authService; + + @MockBean + protected ActionService actionService; + + @MockBean + protected MemberActionService memberActionService; + + @MockBean + protected BillActionService billActionService; + + @MockBean + protected BillActionDetailService billActionDetailService; +} diff --git a/server/src/test/java/server/haengdong/presentation/EventControllerTest.java b/server/src/test/java/server/haengdong/presentation/EventControllerTest.java new file mode 100644 index 000000000..fcfe48d01 --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/EventControllerTest.java @@ -0,0 +1,111 @@ +package server.haengdong.presentation; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.cookie; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import server.haengdong.application.request.EventAppRequest; +import server.haengdong.application.response.EventAppResponse; +import server.haengdong.application.response.EventDetailAppResponse; +import server.haengdong.application.response.MembersAppResponse; +import server.haengdong.presentation.request.EventLoginRequest; +import server.haengdong.presentation.request.EventSaveRequest; +import server.haengdong.presentation.request.MemberNameUpdateRequest; +import server.haengdong.presentation.request.MemberNamesUpdateRequest; + + +class EventControllerTest extends ControllerTestSupport { + + @DisplayName("์ด๋ฒคํŠธ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.") + @Test + void saveEvent() throws Exception { + EventSaveRequest eventSaveRequest = new EventSaveRequest("ํ† ๋‹ค๋ฆฌ", "0987"); + String requestBody = objectMapper.writeValueAsString(eventSaveRequest); + String eventId = "๋ง์ตธํ† ํฐ"; + EventAppResponse eventAppResponse = new EventAppResponse(eventId); + given(eventService.saveEvent(any(EventAppRequest.class))).willReturn(eventAppResponse); + given(authService.createToken(eventId)).willReturn("jwtToken"); + given(authService.getTokenName()).willReturn("eventToken"); + + mockMvc.perform(post("/api/events") + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(cookie().value("eventToken", "jwtToken")) + .andExpect(jsonPath("$.eventId").value("๋ง์ตธํ† ํฐ")); + } + + @DisplayName("ํ† ํฐ์œผ๋กœ ํ–‰์‚ฌ๋ฅผ ์กฐํšŒํ•œ๋‹ค.") + @Test + void findEventTest() throws Exception { + String eventId = "๋ง์ตธํ† ํฐ"; + EventDetailAppResponse eventDetailAppResponse = new EventDetailAppResponse("ํ–‰๋™๋Œ€์žฅ ํšŒ์‹"); + given(eventService.findEvent(eventId)).willReturn(eventDetailAppResponse); + + mockMvc.perform(get("/api/events/{eventId}", eventId)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.eventName").value("ํ–‰๋™๋Œ€์žฅ ํšŒ์‹")); + } + + @DisplayName("ํ–‰์‚ฌ์— ์ฐธ์—ฌํ•œ ์ „์ฒด ์ธ์›์„ ์ค‘๋ณต ์—†์ด ์กฐํšŒํ•œ๋‹ค.") + @Test + void findAllMembersTest() throws Exception { + MembersAppResponse memberAppResponse = new MembersAppResponse(List.of("ํ† ๋‹ค๋ฆฌ", "์ฟ ํ‚ค")); + given(eventService.findAllMembers(anyString())).willReturn(memberAppResponse); + + mockMvc.perform(get("/api/events/{eventId}/members", "TOKEN")) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.memberNames").isArray()) + .andExpect(jsonPath("$.memberNames[0]").value("ํ† ๋‹ค๋ฆฌ")) + .andExpect(jsonPath("$.memberNames[1]").value("์ฟ ํ‚ค")); + } + + @DisplayName("ํ–‰์‚ฌ ์ฐธ์—ฌ ์ธ์›์˜ ์ด๋ฆ„์„ ์ˆ˜์ •ํ•œ๋‹ค.") + @Test + void updateMember() throws Exception { + String token = "TOKEN"; + MemberNamesUpdateRequest memberNameUpdateRequest = new MemberNamesUpdateRequest(List.of( + new MemberNameUpdateRequest("ํ† ๋‹ค๋ง", "ํ† ์Ÿ์ด"), + new MemberNameUpdateRequest("๊ฐ์ž", "๊ณ ๊ตฌ๋งˆ") + )); + + String requestBody = objectMapper.writeValueAsString(memberNameUpdateRequest); + + mockMvc.perform(put("/api/events/{eventId}/members/nameChange", token) + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()); + } + + @DisplayName("ํ–‰์‚ฌ ์–ด๋“œ๋ฏผ์ด ๋กœ๊ทธ์ธํ•œ๋‹ค.") + @Test + void loginEvent() throws Exception { + String token = "TOKEN"; + EventLoginRequest eventLoginRequest = new EventLoginRequest("1234"); + String requestBody = objectMapper.writeValueAsString(eventLoginRequest); + given(authService.createToken(token)).willReturn("jwtToken"); + given(authService.getTokenName()).willReturn("eventToken"); + + mockMvc.perform(post("/api/events/{eventId}/login", token) + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(cookie().value("eventToken", "jwtToken")) + .andExpect(status().isOk()); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java new file mode 100644 index 000000000..f50c70a17 --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java @@ -0,0 +1,74 @@ +package server.haengdong.presentation; + +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import server.haengdong.application.response.CurrentMemberAppResponse; +import server.haengdong.presentation.request.MemberActionsSaveRequest; + +class MemberActionControllerTest extends ControllerTestSupport { + + @DisplayName("์ฐธ์—ฌ์ž ํ–‰๋™์„ ์ถ”๊ฐ€ํ•œ๋‹ค.") + @Test + void saveMemberActionTest() throws Exception { + MemberActionsSaveRequest memberActionsSaveRequest = new MemberActionsSaveRequest( + List.of("์›จ๋””", "์†Œํ•˜", "ํ† ๋‹ค๋ฆฌ", "์ฟ ํ‚ค"), "IN"); + + String requestBody = objectMapper.writeValueAsString(memberActionsSaveRequest); + + mockMvc.perform(post("/api/events/{eventId}/member-actions", "๋ง์ตธํ† ํฐ") + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()); + } + + @DisplayName("ํ˜„์žฌ ์ฐธ์—ฌ ์ธ์›์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.") + @Test + void getCurrentMembers() throws Exception { + List<CurrentMemberAppResponse> currentMemberAppResponses = List.of( + new CurrentMemberAppResponse("์†Œํ•˜"), new CurrentMemberAppResponse("ํ† ๋‹ค๋ฆฌ")); + + given(memberActionService.getCurrentMembers(any())).willReturn(currentMemberAppResponses); + + mockMvc.perform(get("/api/events/{eventId}/members/current", "๋ง์ตธํ† ํฐ") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.memberNames[0]").value(equalTo("์†Œํ•˜"))) + .andExpect(jsonPath("$.memberNames[1]").value(equalTo("ํ† ๋‹ค๋ฆฌ"))); + } + + @DisplayName("์ด๋ฒคํŠธ์— ์†ํ•œ ๋ฉค๋ฒ„ ์•ก์…˜์„ ์‚ญ์ œํ•˜๋ฉด ์ดํ›„์— ๊ธฐ๋ก๋œ ํ•ด๋‹น ์ฐธ์—ฌ์ž์˜ ๋ชจ๋“  ๋ฉค๋ฒ„ ์•ก์…˜์„ ์‚ญ์ œํ•œ๋‹ค.") + @Test + void deleteMemberAction() throws Exception { + String eventId = "๋ง์ตธํ† ํฐ"; + Long actionId = 2L; + + mockMvc.perform(delete("/api/events/{eventId}/member-actions/{actionId}", eventId, actionId)) + .andDo(print()) + .andExpect(status().isOk()); + } + + @DisplayName("ํ–‰์‚ฌ์˜ ์ „์ฒด ์ฐธ์—ฌ์ž ์ค‘์—์„œ ํŠน์ • ์ฐธ์—ฌ์ž์˜ ๋งด๋ฒ„ ์•ก์…˜์„ ์ „๋ถ€ ์‚ญ์ œํ•œ๋‹ค.") + @Test + void deleteMember() throws Exception { + String eventId = "๋ง์ตธํ† ํฐ"; + String memberName = "ํ–‰๋™๋Œ€์žฅ"; + + mockMvc.perform(delete("/api/events/{eventId}/members/{memberName}", eventId, memberName)) + .andDo(print()) + .andExpect(status().isOk()); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/response/StepsResponseTest.java b/server/src/test/java/server/haengdong/presentation/response/StepsResponseTest.java new file mode 100644 index 000000000..051fcae0f --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/response/StepsResponseTest.java @@ -0,0 +1,63 @@ +package server.haengdong.presentation.response; + + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import server.haengdong.application.response.ActionAppResponse; +import server.haengdong.application.response.ActionAppResponse.ActionType; + +class StepsResponseTest { + + @DisplayName("์ด์›ƒํ•œ ๊ฐ™์€ ํƒ€์ž…์˜ ์•ก์…˜๋“ค์„ ๊ทธ๋ฃนํ™” ํ•˜์—ฌ ์‘๋‹ต๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.") + @Test + void of() { + List<ActionAppResponse> actions = List.of( + new ActionAppResponse(1L, "๋ง์ตธ", null, 1L, ActionType.IN), + new ActionAppResponse(2L, "๋ฐฑํ˜ธ", null, 2L, ActionType.IN), + new ActionAppResponse(3L, "๊ฐ์žํƒ•", 10_000L, 3L, ActionType.BILL), + new ActionAppResponse(4L, "์ธ์ƒ๋„ค์ปท", 10_000L, 4L, ActionType.BILL), + new ActionAppResponse(5L, "์†Œํ•˜", null, 5L, ActionType.IN), + new ActionAppResponse(6L, "์›จ๋””", null, 6L, ActionType.IN), + new ActionAppResponse(7L, "๋ง์ตธ", null, 7L, ActionType.OUT), + new ActionAppResponse(8L, "๋ฐฑํ˜ธ", null, 8L, ActionType.OUT), + new ActionAppResponse(9L, "๋…ธ๋ž˜๋ฐฉ", 20_000L, 9L, ActionType.BILL) + ); + + StepsResponse stepsResponse = StepsResponse.of(actions); + + StepsResponse expected = new StepsResponse( + List.of( + new StepResponse("0์ฐจ", "IN", List.of("๋ง์ตธ", "๋ฐฑํ˜ธ"), List.of( + new ActionResponse(1L, "๋ง์ตธ", null, 1L), + new ActionResponse(2L, "๋ฐฑํ˜ธ", null, 2L) + )), + new StepResponse("1์ฐจ", "BILL", List.of("๋ง์ตธ", "๋ฐฑํ˜ธ"), List.of( + new ActionResponse(3L, "๊ฐ์žํƒ•", 10_000L, 3L), + new ActionResponse(4L, "์ธ์ƒ๋„ค์ปท", 10_000L, 4L) + )), + new StepResponse("1์ฐจ", "IN", List.of("๋ง์ตธ", "๋ฐฑํ˜ธ", "์†Œํ•˜", "์›จ๋””"), List.of( + new ActionResponse(5L, "์†Œํ•˜", null, 5L), + new ActionResponse(6L, "์›จ๋””", null, 6L) + )), + new StepResponse("1์ฐจ", "OUT", List.of("์†Œํ•˜", "์›จ๋””"), List.of( + new ActionResponse(7L, "๋ง์ตธ", null, 7L), + new ActionResponse(8L, "๋ฐฑํ˜ธ", null, 8L) + )), + new StepResponse("2์ฐจ", "BILL", List.of("์†Œํ•˜", "์›จ๋””"), List.of( + new ActionResponse(9L, "๋…ธ๋ž˜๋ฐฉ", 20_000L, 9L) + )) + ) + ); + assertThat(stepsResponse).isEqualTo(expected); + } + + @DisplayName("์•ก์…˜์ด ์—†์œผ๋ฉด ๋นˆ ์Šคํƒญ๋“ค์ด ๋งŒ๋“ค์–ด์ง„๋‹ค.") + @Test + void ofEmpty() { + StepsResponse stepsResponse = StepsResponse.of(List.of()); + assertThat(stepsResponse.steps()).isEmpty(); + } +} diff --git a/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java b/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java new file mode 100644 index 000000000..346e81d2d --- /dev/null +++ b/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java @@ -0,0 +1,52 @@ +package server.haengdong.support.extension; + +import jakarta.annotation.PostConstruct; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import java.util.List; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Component +class DatabaseCleaner { + + private static final String REFERENTIAL_FORMAT = "set referential_integrity %b;"; + private static final String TRUNCATE_FORMAT = "truncate table %s restart identity;"; + + @PersistenceContext + private EntityManager em; + private String truncateTablesQuery; + + @PostConstruct + public void createTruncateQuery() { + List<String> tableNames = getTableNames(); + StringBuilder stringBuilder = new StringBuilder(); + + for (String tableName : tableNames) { + String truncateQuery = String.format(TRUNCATE_FORMAT, tableName); + stringBuilder.append(truncateQuery); + } + truncateTablesQuery = stringBuilder.toString(); + } + + private List<String> getTableNames() { + String sql = """ + select table_name + from information_schema.tables + where table_schema = 'PUBLIC' + """; + return em.createNativeQuery(sql).getResultList(); + } + + @Transactional + public void clear() { + em.clear(); + truncate(); + } + + private void truncate() { + em.createNativeQuery(String.format(REFERENTIAL_FORMAT, false)).executeUpdate(); + em.createNativeQuery(truncateTablesQuery).executeUpdate(); + em.createNativeQuery(String.format(REFERENTIAL_FORMAT, true)).executeUpdate(); + } +} diff --git a/server/src/test/java/server/haengdong/support/extension/DatabaseCleanerExtension.java b/server/src/test/java/server/haengdong/support/extension/DatabaseCleanerExtension.java new file mode 100644 index 000000000..653ecadb3 --- /dev/null +++ b/server/src/test/java/server/haengdong/support/extension/DatabaseCleanerExtension.java @@ -0,0 +1,19 @@ +package server.haengdong.support.extension; + +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +public class DatabaseCleanerExtension implements AfterEachCallback { + + @Override + public void afterEach(ExtensionContext context) { + DatabaseCleaner databaseCleaner = getDataCleaner(context); + databaseCleaner.clear(); + } + + private DatabaseCleaner getDataCleaner(ExtensionContext extensionContext) { + return SpringExtension.getApplicationContext(extensionContext) + .getBean(DatabaseCleaner.class); + } +} diff --git a/server/src/test/java/server/haengdong/support/fixture/Fixture.java b/server/src/test/java/server/haengdong/support/fixture/Fixture.java new file mode 100644 index 000000000..6844915d9 --- /dev/null +++ b/server/src/test/java/server/haengdong/support/fixture/Fixture.java @@ -0,0 +1,15 @@ +package server.haengdong.support.fixture; + +import jakarta.servlet.http.Cookie; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.event.Event; + +public class Fixture { + + public static final Event EVENT1 = new Event("์ฟ ํ‚ค", "1234", "TOKEN1"); + public static final Event EVENT2 = new Event("์›จ๋””", "1234", "TOKEN2"); + public static final Cookie EVENT_COOKIE = new Cookie("eventToken", "ํ† ํฐํ† ํฐ"); + public static final Action ACTION = new Action(EVENT1, 1L); + public static final BillAction BILL_ACTION = new BillAction(ACTION, "๋ฝ•์กฑ", 30_000L); +}